1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/js/src/parjs-benchmarks/nbody-seeded.js Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,554 @@ 1.4 +// 1.5 +// NBody adapted from Intel's nbody benchmark. 1.6 +// 1.7 + 1.8 +load(libdir + "util.js"); 1.9 +load(libdir + "seedrandom.js"); 1.10 + 1.11 +var NBody = { 1.12 + Constant: { 1.13 + "deltaTime": 1, // 0.005 in their code. 1.14 + "epsSqr": 50, // softening factor, when they compute, set to 50. 1.15 + "initialVelocity": 8 // set to 0 to turn off 1.16 + }, 1.17 + 1.18 + init: function init(mode, numBodies) { 1.19 + var initPos = new Array(numBodies); 1.20 + var initVel = new Array(numBodies); 1.21 + 1.22 + // initialization of inputs 1.23 + for (var i = 0; i < numBodies; i++) { 1.24 + // [x,y,z] 1.25 + initPos[i] = [Math.floor((Math.random()) * 40000), 1.26 + Math.floor((Math.random()) * 20000), 1.27 + Math.floor((Math.random() - .25) * 50000)]; 1.28 + 1.29 + // [x,y,z,x,y,z] 1.30 + initVel[i] = [(Math.random() - 0.5) * NBody.Constant.initialVelocity, 1.31 + (Math.random() - 0.5) * NBody.Constant.initialVelocity, 1.32 + (Math.random()) * NBody.Constant.initialVelocity + 10, 1.33 + 1.34 + (Math.random() - 0.5) * NBody.Constant.initialVelocity, 1.35 + (Math.random() - 0.5) * NBody.Constant.initialVelocity, 1.36 + (Math.random()) * NBody.Constant.initialVelocity]; 1.37 + } 1.38 + 1.39 + NBody.private = {}; 1.40 + 1.41 + if (mode === "par") { 1.42 + NBody.private.pos = new ParallelArray(initPos); 1.43 + NBody.private.vel = new ParallelArray(initVel); 1.44 + } else { 1.45 + NBody.private.pos = initPos; 1.46 + NBody.private.vel = initVel; 1.47 + } 1.48 + 1.49 + NBody.numBodies = numBodies; 1.50 + NBody.time = 0; 1.51 + }, 1.52 + 1.53 + // Parallel 1.54 + 1.55 + tickPar: function tickPar() { 1.56 + NBody.private.vel = new ParallelArray([NBody.numBodies], NBody.velocityPar); 1.57 + NBody.private.pos = new ParallelArray([NBody.numBodies], NBody.positionPar); 1.58 + NBody.time++; 1.59 + }, 1.60 + 1.61 + velocityPar: function velocityPar(index) { 1.62 + var pos = NBody.private.pos; 1.63 + var vel = NBody.private.vel; 1.64 + 1.65 + var deltaTime = NBody.Constant.deltaTime; 1.66 + var epsSqr = NBody.Constant.epsSqr; 1.67 + var time = NBody.time; 1.68 + 1.69 + var shape = vel.shape[0]; 1.70 + 1.71 + var newVel; 1.72 + var newX, newY, newZ; 1.73 + var newX2, newY2, newZ2; 1.74 + 1.75 + var cX = Math.cos(time / 22) * -4200; 1.76 + var cY = Math.sin(time / 14) * 9200; 1.77 + var cZ = Math.sin(time / 27) * 6000; 1.78 + 1.79 + // pull to center 1.80 + var maxDistance = 3400; 1.81 + var pullStrength = .042; 1.82 + 1.83 + var speedLimit = 8; 1.84 + 1.85 + // zones 1.86 + var zone = 400; 1.87 + var repel = 100; 1.88 + var align = 300; 1.89 + var attract = 100; 1.90 + 1.91 + if (time < 500) { 1.92 + speedLimit = 2000; 1.93 + var attractPower = 100.9; 1.94 + } else { 1.95 + speedLimit = .2; 1.96 + attractPower = 20.9; 1.97 + } 1.98 + 1.99 + var zoneSqrd = zone * zone + zone * zone + zone * zone; 1.100 + 1.101 + var accX = 0, accY = 0, accZ = 0; 1.102 + var accX2 = 0, accY2 = 0, accZ2 = 0; 1.103 + var i; 1.104 + 1.105 + // define particle 1 center distance 1.106 + var dirToCenterX = cX - pos.get(index)[0]; 1.107 + var dirToCenterY = cY - pos.get(index)[1]; 1.108 + var dirToCenterZ = cZ - pos.get(index)[2]; 1.109 + 1.110 + var distanceSquaredTo = dirToCenterX * dirToCenterX + dirToCenterY * dirToCenterY + dirToCenterZ * dirToCenterZ; 1.111 + var distToCenter = Math.sqrt(distanceSquaredTo); 1.112 + 1.113 + // orient to center 1.114 + if (distToCenter > maxDistance) { 1.115 + var velc = (distToCenter - maxDistance) * pullStrength; 1.116 + if (time < 200) 1.117 + velc = .2; 1.118 + else velc = (distToCenter - maxDistance) * pullStrength; 1.119 + 1.120 + accX += (dirToCenterX / distToCenter) * velc; 1.121 + accY += (dirToCenterY / distToCenter) * velc; 1.122 + accZ += (dirToCenterZ / distToCenter) * velc; 1.123 + } 1.124 + 1.125 + for (i = 0; i < shape; i = i + 1) { 1.126 + var rx = pos.get(i)[0] - pos.get(index)[0]; 1.127 + var ry = pos.get(i)[1] - pos.get(index)[1]; 1.128 + var rz = pos.get(i)[2] - pos.get(index)[2]; 1.129 + 1.130 + // make sure we are not testing the particle against its own position 1.131 + var areSame = 0; 1.132 + if (pos.get(i)[0] == pos.get(index)[0] && pos.get(i)[1] == pos.get(index)[1] && pos.get(i)[2] == pos.get(index)[2]) 1.133 + areSame += 1; 1.134 + 1.135 + var distSqrd = rx * rx + ry * ry + rz * rz; 1.136 + 1.137 + // cant use eqals to test, only <= or >= WTF 1.138 + if (distSqrd < zoneSqrd && areSame <= 0) { 1.139 + var length = Math.sqrt(distSqrd); 1.140 + var percent = distSqrd / zoneSqrd; 1.141 + 1.142 + if (distSqrd < repel) { 1.143 + var F = (repel / percent - 1) * .025; 1.144 + 1.145 + var normalRx = (rx / length) * F; 1.146 + var normalRy = (ry / length) * F; 1.147 + var normalRz = (rz / length) * F; 1.148 + 1.149 + accX = accX + normalRx; 1.150 + accY = accY + normalRy; 1.151 + accZ = accZ + normalRz; 1.152 + 1.153 + accX2 = accX2 - normalRx; 1.154 + accY2 = accY2 - normalRy; 1.155 + accZ2 = accZ2 - normalRz; 1.156 + } else if (distSqrd < align) { //align 1.157 + var threshDelta = align - repel; 1.158 + var adjustedPercent = (percent - repel) / threshDelta; 1.159 + var Q = (.5 - Math.cos(adjustedPercent * 3.14159265 * 2) * .5 + .5) * 100.9; 1.160 + 1.161 + // get velocity 2 1.162 + var velX2 = vel.get(i)[4]; 1.163 + var velY2 = vel.get(i)[5]; 1.164 + var velZ2 = vel.get(i)[6]; 1.165 + 1.166 + var velLength2 = Math.sqrt(velX2 * velX2 + velY2 * velY2 + velZ2 * velZ2); 1.167 + 1.168 + // normalize vel2 and multiply by factor 1.169 + velX2 = (velX2 / velLength2) * Q; 1.170 + velY2 = (velY2 / velLength2) * Q; 1.171 + velZ2 = (velZ2 / velLength2) * Q; 1.172 + 1.173 + // get own velocity 1.174 + var velX = vel.get(i)[0]; 1.175 + var velY = vel.get(i)[1]; 1.176 + var velZ = vel.get(i)[2]; 1.177 + 1.178 + var velLength = Math.sqrt(velX * velX + velY * velY + velZ * velZ); 1.179 + 1.180 + // normalize own velocity 1.181 + velX = (velX / velLength) * Q; 1.182 + velY = (velY / velLength) * Q; 1.183 + velZ = (velZ / velLength) * Q; 1.184 + 1.185 + accX += velX2; 1.186 + accY += velY2; 1.187 + accZ += velZ2; 1.188 + 1.189 + accX2 += velX; 1.190 + accY2 += velY; 1.191 + accZ2 += velZ; 1.192 + } 1.193 + 1.194 + if (distSqrd > attract) { // attract 1.195 + var threshDelta2 = 1 - attract; 1.196 + var adjustedPercent2 = (percent - attract) / threshDelta2; 1.197 + var C = (1 - (Math.cos(adjustedPercent2 * 3.14159265 * 2) * 0.5 + 0.5)) * attractPower; 1.198 + 1.199 + // normalize the distance vector 1.200 + var dx = (rx / (length)) * C; 1.201 + var dy = (ry / (length)) * C; 1.202 + var dz = (rz / (length)) * C; 1.203 + 1.204 + accX += dx; 1.205 + accY += dy; 1.206 + accZ += dz; 1.207 + 1.208 + accX2 -= dx; 1.209 + accY2 -= dy; 1.210 + accZ2 -= dz; 1.211 + } 1.212 + } 1.213 + } 1.214 + 1.215 + // Speed limits 1.216 + if (time > 500) { 1.217 + var accSquared = accX * accX + accY * accY + accZ * accZ; 1.218 + if (accSquared > speedLimit) { 1.219 + accX = accX * .015; 1.220 + accY = accY * .015; 1.221 + accZ = accZ * .015; 1.222 + } 1.223 + 1.224 + var accSquared2 = accX2 * accX2 + accY2 * accY2 + accZ2 * accZ2; 1.225 + if (accSquared2 > speedLimit) { 1.226 + accX2 = accX2 * .015; 1.227 + accY2 = accY2 * .015; 1.228 + accZ2 = accZ2 * .015; 1.229 + } 1.230 + } 1.231 + 1.232 + // Caclulate new velocity 1.233 + newX = (vel.get(index)[0]) + accX; 1.234 + newY = (vel.get(index)[1]) + accY; 1.235 + newZ = (vel.get(index)[2]) + accZ; 1.236 + 1.237 + newX2 = (vel.get(index)[3]) + accX2; 1.238 + newY2 = (vel.get(index)[4]) + accY2; 1.239 + newZ2 = (vel.get(index)[5]) + accZ2; 1.240 + 1.241 + if (time < 500) { 1.242 + var acs = newX2 * newX2 + newY2 * newY2 + newZ2 * newZ2; 1.243 + if (acs > speedLimit) { 1.244 + newX2 = newX2 * .15; 1.245 + newY2 = newY2 * .15; 1.246 + newZ2 = newZ2 * .15; 1.247 + } 1.248 + 1.249 + var acs2 = newX * newX + newY * newY + newZ * newZ; 1.250 + if (acs2 > speedLimit) { 1.251 + newX = newX * .15; 1.252 + newY = newY * .15; 1.253 + newZ = newZ * .15; 1.254 + } 1.255 + } 1.256 + 1.257 + return [newX, newY, newZ, newX2, newY2, newZ2]; 1.258 + }, 1.259 + 1.260 + positionPar: function positionPar(index) { 1.261 + var vel = NBody.private.vel; 1.262 + var pos = NBody.private.pos; 1.263 + 1.264 + var x = 0; 1.265 + var y = 0; 1.266 + var z = 0; 1.267 + 1.268 + var velX = vel.get(index)[0]; 1.269 + var velY = vel.get(index)[1]; 1.270 + var velZ = vel.get(index)[2]; 1.271 + 1.272 + var velX2 = vel.get(index)[3]; 1.273 + var velY2 = vel.get(index)[4]; 1.274 + var velZ2 = vel.get(index)[5]; 1.275 + 1.276 + var netVelX = (velX - velX2); 1.277 + var netVelY = (velY - velY2); 1.278 + var netVelZ = (velZ - velZ2); 1.279 + 1.280 + x = pos.get(index)[0] + (netVelX); 1.281 + y = pos.get(index)[1] + (netVelY); 1.282 + z = pos.get(index)[2] + (netVelZ); 1.283 + 1.284 + return [x, y, z]; 1.285 + }, 1.286 + 1.287 + // Sequential 1.288 + 1.289 + tickSeq: function tickSeq() { 1.290 + var numBodies = NBody.numBodies; 1.291 + var newVel = new Array(numBodies); 1.292 + var newPos = new Array(numBodies); 1.293 + 1.294 + for (var i = 0; i < numBodies; i++) 1.295 + newVel[i] = NBody.velocitySeq(i); 1.296 + 1.297 + for (var i = 0; i < numBodies; i++) 1.298 + newPos[i] = NBody.positionSeq(i); 1.299 + 1.300 + NBody.private.vel = newVel; 1.301 + NBody.private.pos = newPos; 1.302 + 1.303 + NBody.time++; 1.304 + }, 1.305 + 1.306 + velocitySeq: function velocitySeq(index) { 1.307 + var vel = NBody.private.vel; 1.308 + var pos = NBody.private.pos; 1.309 + 1.310 + var deltaTime = NBody.Constant.deltaTime; 1.311 + var epsSqr = NBody.Constant.epsSqr; 1.312 + var time = NBody.time; 1.313 + 1.314 + var shape = pos.length; 1.315 + 1.316 + var newVel; 1.317 + var newX, newY, newZ; 1.318 + var newX2, newY2, newZ2; 1.319 + 1.320 + var cX = Math.cos(time / 22) * -4200; 1.321 + var cY = Math.sin(time / 14) * 9200; 1.322 + var cZ = Math.sin(time / 27) * 6000; 1.323 + 1.324 + // pull to center 1.325 + var maxDistance = 3400; 1.326 + var pullStrength = .042; 1.327 + 1.328 + var speedLimit = 8; 1.329 + 1.330 + // zones 1.331 + var zone = 400; 1.332 + var repel = 100; 1.333 + var align = 300; 1.334 + var attract = 100; 1.335 + 1.336 + 1.337 + if (time < 500) { 1.338 + speedLimit = 2000; 1.339 + var attractPower = 100.9; 1.340 + } else { 1.341 + speedLimit = .2; 1.342 + attractPower = 20.9; 1.343 + } 1.344 + 1.345 + var zoneSqrd = zone * zone + zone * zone + zone * zone; 1.346 + 1.347 + var accX = 0, accY = 0, accZ = 0; 1.348 + var accX2 = 0, accY2 = 0, accZ2 = 0; 1.349 + var i; 1.350 + 1.351 + // define particle 1 center distance 1.352 + var dirToCenterX = cX - pos[index][0]; 1.353 + var dirToCenterY = cY - pos[index][1]; 1.354 + var dirToCenterZ = cZ - pos[index][2]; 1.355 + 1.356 + var distanceSquaredTo = dirToCenterX * dirToCenterX + dirToCenterY * dirToCenterY + dirToCenterZ * dirToCenterZ; 1.357 + var distToCenter = Math.sqrt(distanceSquaredTo); 1.358 + 1.359 + // orient to center 1.360 + if (distToCenter > maxDistance) { 1.361 + var velc = (distToCenter - maxDistance) * pullStrength; 1.362 + if (time < 200) 1.363 + velc = .2; 1.364 + else velc = (distToCenter - maxDistance) * pullStrength; 1.365 + 1.366 + accX += (dirToCenterX / distToCenter) * velc; 1.367 + accY += (dirToCenterY / distToCenter) * velc; 1.368 + accZ += (dirToCenterZ / distToCenter) * velc; 1.369 + } 1.370 + 1.371 + for (i = 0; i < shape; i = i + 1) { 1.372 + var rx = pos[i][0] - pos[index][0]; 1.373 + var ry = pos[i][1] - pos[index][1]; 1.374 + var rz = pos[i][2] - pos[index][2]; 1.375 + 1.376 + var areSame = 0; 1.377 + if (pos[i][0] == pos[index][0] && pos[i][1] == pos[index][1] && pos[i][2] == pos[index][2]) 1.378 + areSame += 1; 1.379 + 1.380 + var distSqrd = rx * rx + ry * ry + rz * rz; 1.381 + 1.382 + // cant use eqals to test, only <= or >= WTF 1.383 + if (distSqrd < zoneSqrd && areSame <= 0) { 1.384 + var length = Math.sqrt(distSqrd); 1.385 + var percent = distSqrd / zoneSqrd; 1.386 + 1.387 + 1.388 + if (distSqrd < repel) { 1.389 + var F = (repel / percent - 1) * .025; 1.390 + 1.391 + var normalRx = (rx / length) * F; 1.392 + var normalRy = (ry / length) * F; 1.393 + var normalRz = (rz / length) * F; 1.394 + 1.395 + accX = accX + normalRx; 1.396 + accY = accY + normalRy; 1.397 + accZ = accZ + normalRz; 1.398 + 1.399 + accX2 = accX2 - normalRx; 1.400 + accY2 = accY2 - normalRy; 1.401 + accZ2 = accZ2 - normalRz; 1.402 + } else if (distSqrd < align) { //align 1.403 + var threshDelta = align - repel; 1.404 + var adjustedPercent = (percent - repel) / threshDelta; 1.405 + var Q = (.5 - Math.cos(adjustedPercent * 3.14159265 * 2) * .5 + .5) * 100; 1.406 + 1.407 + // get velocity 2 1.408 + var velX2 = vel[i][3]; 1.409 + var velY2 = vel[i][4]; 1.410 + var velZ2 = vel[i][5]; 1.411 + 1.412 + var velLength2 = Math.sqrt(velX2 * velX2 + velY2 * velY2 + velZ2 * velZ2); 1.413 + 1.414 + // normalize vel2 and multiply by factor 1.415 + velX2 = (velX2 / velLength2) * Q; 1.416 + velY2 = (velY2 / velLength2) * Q; 1.417 + velZ2 = (velZ2 / velLength2) * Q; 1.418 + 1.419 + // get own velocity 1.420 + var velX = vel[i][0]; 1.421 + var velY = vel[i][1]; 1.422 + var velZ = vel[i][2]; 1.423 + 1.424 + var velLength = Math.sqrt(velX * velX + velY * velY + velZ * velZ); 1.425 + 1.426 + // normalize own velocity 1.427 + velX = (velX / velLength) * Q; 1.428 + velY = (velY / velLength) * Q; 1.429 + velZ = (velZ / velLength) * Q; 1.430 + 1.431 + accX += velX2; 1.432 + accY += velY2; 1.433 + accZ += velZ2; 1.434 + 1.435 + accX2 += velX; 1.436 + accY2 += velY; 1.437 + accZ2 += velZ; 1.438 + } 1.439 + 1.440 + if (distSqrd > attract) { //attract 1.441 + var threshDelta2 = 1 - align; 1.442 + var adjustedPercent2 = (percent - align) / threshDelta2; 1.443 + var C = (1 - (Math.cos(adjustedPercent2 * 3.14159265 * 2) * 0.5 + 0.5)) * attractPower; 1.444 + 1.445 + // normalize the distance vector 1.446 + var dx = (rx / (length)) * C; 1.447 + var dy = (ry / (length)) * C; 1.448 + var dz = (rz / (length)) * C; 1.449 + 1.450 + debug = 1.1; 1.451 + 1.452 + accX += dx; 1.453 + accY += dy; 1.454 + accZ += dz; 1.455 + 1.456 + accX2 -= dx; 1.457 + accY2 -= dy; 1.458 + accZ2 -= dz; 1.459 + } 1.460 + } 1.461 + } 1.462 + 1.463 + // enforce speed limits 1.464 + if (time > 500) { 1.465 + var accSquared = accX * accX + accY * accY + accZ * accZ; 1.466 + if (accSquared > speedLimit) { 1.467 + accX = accX * .015; 1.468 + accY = accY * .015; 1.469 + accZ = accZ * .015; 1.470 + } 1.471 + 1.472 + var accSquared2 = accX2 * accX2 + accY2 * accY2 + accZ2 * accZ2; 1.473 + if (accSquared2 > speedLimit) { 1.474 + accX2 = accX2 * .015; 1.475 + accY2 = accY2 * .015; 1.476 + accZ2 = accZ2 * .015; 1.477 + } 1.478 + } 1.479 + 1.480 + // Caclulate new velocity 1.481 + newX = vel[index][0] + accX; 1.482 + newY = vel[index][1] + accY; 1.483 + newZ = vel[index][2] + accZ; 1.484 + 1.485 + newX2 = vel[index][3] + accX2; 1.486 + newY2 = vel[index][4] + accY2; 1.487 + newZ2 = vel[index][5] + accZ2; 1.488 + 1.489 + if (time < 500) { 1.490 + var acs = newX2 * newX2 + newY2 * newY2 + newZ2 * newZ2; 1.491 + if (acs > speedLimit) { 1.492 + newX2 = newX2 * .15; 1.493 + newY2 = newY2 * .15; 1.494 + newZ2 = newZ2 * .15; 1.495 + } 1.496 + 1.497 + var acs2 = newX * newX + newY * newY + newZ * newZ; 1.498 + if (acs2 > speedLimit) { 1.499 + newX = newX * .15; 1.500 + newY = newY * .15; 1.501 + newZ = newZ * .15; 1.502 + } 1.503 + } 1.504 + 1.505 + return [newX, newY, newZ, newX2, newY2, newZ2]; 1.506 + }, 1.507 + 1.508 + positionSeq: function positionSeq(index) { 1.509 + var vel = NBody.private.vel; 1.510 + var pos = NBody.private.pos; 1.511 + 1.512 + var x = 0; 1.513 + var y = 0; 1.514 + var z = 0; 1.515 + 1.516 + var velX = vel[index][0]; 1.517 + var velY = vel[index][1]; 1.518 + var velZ = vel[index][2]; 1.519 + 1.520 + var velX2 = vel[index][3]; 1.521 + var velY2 = vel[index][4]; 1.522 + var velZ2 = vel[index][5]; 1.523 + 1.524 + var netX = (velX - velX2); 1.525 + var netY = (velY - velY2); 1.526 + var netZ = (velZ - velZ2); 1.527 + 1.528 + x = pos[index][0] + netX; 1.529 + y = pos[index][1] + netY; 1.530 + z = pos[index][2] + netZ; 1.531 + 1.532 + return [x, y, z]; 1.533 + } 1.534 +}; 1.535 + 1.536 +function emulateNBody(mode, numBodies, ticks) { 1.537 + NBody.init(mode, numBodies); 1.538 + for (var i = 0; i < ticks; i++) { 1.539 + var start = Date.now(); 1.540 + if (mode === "par") 1.541 + NBody.tickPar(); 1.542 + else 1.543 + NBody.tickSeq(); 1.544 + //print(NBody.private.pos); 1.545 + print(mode + " bodies=" + numBodies + " tick=" + (i+1) + "/" + ticks + ": " + (Date.now() - start) + " ms"); 1.546 + } 1.547 +} 1.548 + 1.549 +// Using 4000 bodies going off Rick's comment as 4000 being a typical workload. 1.550 +const NUMBODIES = 4000; 1.551 +const TICKS = 10; 1.552 + 1.553 +Math.seedrandom("seed"); 1.554 + 1.555 +benchmark("NBODY", 1, DEFAULT_MEASURE, 1.556 + function () { emulateNBody("seq", NUMBODIES, TICKS); }, 1.557 + function () { emulateNBody("par", NUMBODIES, TICKS); });