js/src/parjs-benchmarks/nbody-seeded.js

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     1 //
     2 // NBody adapted from Intel's nbody benchmark.
     3 //
     5 load(libdir + "util.js");
     6 load(libdir + "seedrandom.js");
     8 var NBody = {
     9   Constant: {
    10     "deltaTime": 1,     // 0.005 in their code.
    11     "epsSqr": 50,       // softening factor, when they compute, set to 50.
    12     "initialVelocity": 8 // set to 0 to turn off
    13   },
    15   init: function init(mode, numBodies) {
    16     var initPos = new Array(numBodies);
    17     var initVel = new Array(numBodies);
    19     // initialization of inputs
    20     for (var i = 0; i < numBodies; i++) {
    21       // [x,y,z]
    22       initPos[i] = [Math.floor((Math.random()) * 40000),
    23                     Math.floor((Math.random()) * 20000),
    24                     Math.floor((Math.random() - .25) * 50000)];
    26       // [x,y,z,x,y,z]
    27       initVel[i] = [(Math.random() - 0.5) * NBody.Constant.initialVelocity,
    28                     (Math.random() - 0.5) * NBody.Constant.initialVelocity,
    29                     (Math.random()) * NBody.Constant.initialVelocity + 10,
    31                     (Math.random() - 0.5) * NBody.Constant.initialVelocity,
    32                     (Math.random() - 0.5) * NBody.Constant.initialVelocity,
    33                     (Math.random()) * NBody.Constant.initialVelocity];
    34     }
    36     NBody.private = {};
    38     if (mode === "par") {
    39       NBody.private.pos = new ParallelArray(initPos);
    40       NBody.private.vel = new ParallelArray(initVel);
    41     } else {
    42       NBody.private.pos = initPos;
    43       NBody.private.vel = initVel;
    44     }
    46     NBody.numBodies = numBodies;
    47     NBody.time = 0;
    48   },
    50   // Parallel
    52   tickPar: function tickPar() {
    53     NBody.private.vel = new ParallelArray([NBody.numBodies], NBody.velocityPar);
    54     NBody.private.pos = new ParallelArray([NBody.numBodies], NBody.positionPar);
    55     NBody.time++;
    56   },
    58   velocityPar: function velocityPar(index) {
    59     var pos = NBody.private.pos;
    60     var vel = NBody.private.vel;
    62     var deltaTime = NBody.Constant.deltaTime;
    63     var epsSqr = NBody.Constant.epsSqr;
    64     var time = NBody.time;
    66     var shape = vel.shape[0];
    68     var newVel;
    69     var newX, newY, newZ;
    70     var newX2, newY2, newZ2;
    72     var cX = Math.cos(time / 22) * -4200;
    73     var cY = Math.sin(time / 14) * 9200;
    74     var cZ = Math.sin(time / 27) * 6000;
    76     // pull to center
    77     var maxDistance = 3400;
    78     var pullStrength = .042;
    80     var speedLimit = 8;
    82     // zones
    83     var zone = 400;
    84     var repel = 100;
    85     var align = 300;
    86     var attract = 100;
    88     if (time < 500) {
    89       speedLimit = 2000;
    90       var attractPower = 100.9;
    91     } else {
    92       speedLimit = .2;
    93       attractPower = 20.9;
    94     }
    96     var zoneSqrd = zone * zone + zone * zone + zone * zone;
    98     var accX = 0, accY = 0, accZ = 0;
    99     var accX2 = 0, accY2 = 0, accZ2 = 0;
   100     var i;
   102     // define particle 1 center distance
   103     var dirToCenterX = cX - pos.get(index)[0];
   104     var dirToCenterY = cY - pos.get(index)[1];
   105     var dirToCenterZ = cZ - pos.get(index)[2];
   107     var distanceSquaredTo = dirToCenterX * dirToCenterX + dirToCenterY * dirToCenterY + dirToCenterZ * dirToCenterZ;
   108     var distToCenter = Math.sqrt(distanceSquaredTo);
   110     // orient to center
   111     if (distToCenter > maxDistance) {
   112       var velc = (distToCenter - maxDistance) * pullStrength;
   113       if (time < 200)
   114         velc = .2;
   115       else velc = (distToCenter - maxDistance) * pullStrength;
   117       accX += (dirToCenterX / distToCenter) * velc;
   118       accY += (dirToCenterY / distToCenter) * velc;
   119       accZ += (dirToCenterZ / distToCenter) * velc;
   120     }
   122     for (i = 0; i < shape; i = i + 1) {
   123       var rx = pos.get(i)[0] - pos.get(index)[0];
   124       var ry = pos.get(i)[1] - pos.get(index)[1];
   125       var rz = pos.get(i)[2] - pos.get(index)[2];
   127       // make sure we are not testing the particle against its own position
   128       var areSame = 0;
   129       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])
   130         areSame += 1;
   132       var distSqrd = rx * rx + ry * ry + rz * rz;
   134       // cant use eqals to test, only <= or >= WTF
   135       if (distSqrd < zoneSqrd && areSame <= 0) {
   136         var length = Math.sqrt(distSqrd);
   137         var percent = distSqrd / zoneSqrd;
   139         if (distSqrd < repel) {
   140           var F = (repel / percent - 1) * .025;
   142           var normalRx = (rx / length) * F;
   143           var normalRy = (ry / length) * F;
   144           var normalRz = (rz / length) * F;
   146           accX = accX + normalRx;
   147           accY = accY + normalRy;
   148           accZ = accZ + normalRz;
   150           accX2 = accX2 - normalRx;
   151           accY2 = accY2 - normalRy;
   152           accZ2 = accZ2 - normalRz;
   153         } else if (distSqrd < align) { //align
   154           var threshDelta = align - repel;
   155           var adjustedPercent = (percent - repel) / threshDelta;
   156           var Q = (.5 - Math.cos(adjustedPercent * 3.14159265 * 2) * .5 + .5) * 100.9;
   158           // get velocity 2
   159           var velX2 = vel.get(i)[4];
   160           var velY2 = vel.get(i)[5];
   161           var velZ2 = vel.get(i)[6];
   163           var velLength2 = Math.sqrt(velX2 * velX2 + velY2 * velY2 + velZ2 * velZ2);
   165           // normalize vel2 and multiply by factor
   166           velX2 = (velX2 / velLength2) * Q;
   167           velY2 = (velY2 / velLength2) * Q;
   168           velZ2 = (velZ2 / velLength2) * Q;
   170           // get own velocity
   171           var velX = vel.get(i)[0];
   172           var velY = vel.get(i)[1];
   173           var velZ = vel.get(i)[2];
   175           var velLength = Math.sqrt(velX * velX + velY * velY + velZ * velZ);
   177           // normalize own velocity
   178           velX = (velX / velLength) * Q;
   179           velY = (velY / velLength) * Q;
   180           velZ = (velZ / velLength) * Q;
   182           accX += velX2;
   183           accY += velY2;
   184           accZ += velZ2;
   186           accX2 += velX;
   187           accY2 += velY;
   188           accZ2 += velZ;
   189         }
   191         if (distSqrd > attract) { // attract
   192           var threshDelta2 = 1 - attract;
   193           var adjustedPercent2 = (percent - attract) / threshDelta2;
   194           var C = (1 - (Math.cos(adjustedPercent2 * 3.14159265 * 2) * 0.5 + 0.5)) * attractPower;
   196           // normalize the distance vector
   197           var dx = (rx / (length)) * C;
   198           var dy = (ry / (length)) * C;
   199           var dz = (rz / (length)) * C;
   201           accX += dx;
   202           accY += dy;
   203           accZ += dz;
   205           accX2 -= dx;
   206           accY2 -= dy;
   207           accZ2 -= dz;
   208         }
   209       }
   210     }
   212     // Speed limits
   213     if (time > 500) {
   214       var accSquared = accX * accX + accY * accY + accZ * accZ;
   215       if (accSquared > speedLimit) {
   216         accX = accX * .015;
   217         accY = accY * .015;
   218         accZ = accZ * .015;
   219       }
   221       var accSquared2 = accX2 * accX2 + accY2 * accY2 + accZ2 * accZ2;
   222       if (accSquared2 > speedLimit) {
   223         accX2 = accX2 * .015;
   224         accY2 = accY2 * .015;
   225         accZ2 = accZ2 * .015;
   226       }
   227     }
   229     // Caclulate new velocity
   230     newX = (vel.get(index)[0]) + accX;
   231     newY = (vel.get(index)[1]) + accY;
   232     newZ = (vel.get(index)[2]) + accZ;
   234     newX2 = (vel.get(index)[3]) + accX2;
   235     newY2 = (vel.get(index)[4]) + accY2;
   236     newZ2 = (vel.get(index)[5]) + accZ2;
   238     if (time < 500) {
   239       var acs = newX2 * newX2 + newY2 * newY2 + newZ2 * newZ2;
   240       if (acs > speedLimit) {
   241         newX2 = newX2 * .15;
   242         newY2 = newY2 * .15;
   243         newZ2 = newZ2 * .15;
   244       }
   246       var acs2 = newX * newX + newY * newY + newZ * newZ;
   247       if (acs2 > speedLimit) {
   248         newX = newX * .15;
   249         newY = newY * .15;
   250         newZ = newZ * .15;
   251       }
   252     }
   254     return [newX, newY, newZ, newX2, newY2, newZ2];
   255   },
   257   positionPar: function positionPar(index) {
   258     var vel = NBody.private.vel;
   259     var pos = NBody.private.pos;
   261     var x = 0;
   262     var y = 0;
   263     var z = 0;
   265     var velX = vel.get(index)[0];
   266     var velY = vel.get(index)[1];
   267     var velZ = vel.get(index)[2];
   269     var velX2 = vel.get(index)[3];
   270     var velY2 = vel.get(index)[4];
   271     var velZ2 = vel.get(index)[5];
   273     var netVelX = (velX - velX2);
   274     var netVelY = (velY - velY2);
   275     var netVelZ = (velZ - velZ2);
   277     x = pos.get(index)[0] + (netVelX);
   278     y = pos.get(index)[1] + (netVelY);
   279     z = pos.get(index)[2] + (netVelZ);
   281     return [x, y, z];
   282   },
   284   // Sequential
   286   tickSeq: function tickSeq() {
   287     var numBodies = NBody.numBodies;
   288     var newVel = new Array(numBodies);
   289     var newPos = new Array(numBodies);
   291     for (var i = 0; i < numBodies; i++)
   292       newVel[i] = NBody.velocitySeq(i);
   294     for (var i = 0; i < numBodies; i++)
   295       newPos[i] = NBody.positionSeq(i);
   297     NBody.private.vel = newVel;
   298     NBody.private.pos = newPos;
   300     NBody.time++;
   301   },
   303   velocitySeq: function velocitySeq(index) {
   304     var vel = NBody.private.vel;
   305     var pos = NBody.private.pos;
   307     var deltaTime = NBody.Constant.deltaTime;
   308     var epsSqr = NBody.Constant.epsSqr;
   309     var time = NBody.time;
   311     var shape = pos.length;
   313     var newVel;
   314     var newX, newY, newZ;
   315     var newX2, newY2, newZ2;
   317     var cX = Math.cos(time / 22) * -4200;
   318     var cY = Math.sin(time / 14) * 9200;
   319     var cZ = Math.sin(time / 27) * 6000;
   321     // pull to center
   322     var maxDistance = 3400;
   323     var pullStrength = .042;
   325     var speedLimit = 8;
   327     // zones
   328     var zone = 400;
   329     var repel = 100;
   330     var align = 300;
   331     var attract = 100;
   334     if (time < 500) {
   335       speedLimit = 2000;
   336       var attractPower = 100.9;
   337     } else {
   338       speedLimit = .2;
   339       attractPower = 20.9;
   340     }
   342     var zoneSqrd = zone * zone + zone * zone + zone * zone;
   344     var accX = 0, accY = 0, accZ = 0;
   345     var accX2 = 0, accY2 = 0, accZ2 = 0;
   346     var i;
   348     // define particle 1 center distance
   349     var dirToCenterX = cX - pos[index][0];
   350     var dirToCenterY = cY - pos[index][1];
   351     var dirToCenterZ = cZ - pos[index][2];
   353     var distanceSquaredTo = dirToCenterX * dirToCenterX + dirToCenterY * dirToCenterY + dirToCenterZ * dirToCenterZ;
   354     var distToCenter = Math.sqrt(distanceSquaredTo);
   356     // orient to center
   357     if (distToCenter > maxDistance) {
   358       var velc = (distToCenter - maxDistance) * pullStrength;
   359       if (time < 200)
   360         velc = .2;
   361       else velc = (distToCenter - maxDistance) * pullStrength;
   363       accX += (dirToCenterX / distToCenter) * velc;
   364       accY += (dirToCenterY / distToCenter) * velc;
   365       accZ += (dirToCenterZ / distToCenter) * velc;
   366     }
   368     for (i = 0; i < shape; i = i + 1) {
   369       var rx = pos[i][0] - pos[index][0];
   370       var ry = pos[i][1] - pos[index][1];
   371       var rz = pos[i][2] - pos[index][2];
   373       var areSame = 0;
   374       if (pos[i][0] == pos[index][0] && pos[i][1] == pos[index][1] && pos[i][2] == pos[index][2])
   375         areSame += 1;
   377       var distSqrd = rx * rx + ry * ry + rz * rz;
   379       // cant use eqals to test, only <= or >= WTF
   380       if (distSqrd < zoneSqrd && areSame <= 0) {
   381         var length = Math.sqrt(distSqrd);
   382         var percent = distSqrd / zoneSqrd;
   385         if (distSqrd < repel) {
   386           var F = (repel / percent - 1) * .025;
   388           var normalRx = (rx / length) * F;
   389           var normalRy = (ry / length) * F;
   390           var normalRz = (rz / length) * F;
   392           accX = accX + normalRx;
   393           accY = accY + normalRy;
   394           accZ = accZ + normalRz;
   396           accX2 = accX2 - normalRx;
   397           accY2 = accY2 - normalRy;
   398           accZ2 = accZ2 - normalRz;
   399         } else if (distSqrd < align) { //align
   400           var threshDelta = align - repel;
   401           var adjustedPercent = (percent - repel) / threshDelta;
   402           var Q = (.5 - Math.cos(adjustedPercent * 3.14159265 * 2) * .5 + .5) * 100;
   404           // get velocity 2
   405           var velX2 = vel[i][3];
   406           var velY2 = vel[i][4];
   407           var velZ2 = vel[i][5];
   409           var velLength2 = Math.sqrt(velX2 * velX2 + velY2 * velY2 + velZ2 * velZ2);
   411           // normalize vel2 and multiply by factor
   412           velX2 = (velX2 / velLength2) * Q;
   413           velY2 = (velY2 / velLength2) * Q;
   414           velZ2 = (velZ2 / velLength2) * Q;
   416           // get own velocity
   417           var velX = vel[i][0];
   418           var velY = vel[i][1];
   419           var velZ = vel[i][2];
   421           var velLength = Math.sqrt(velX * velX + velY * velY + velZ * velZ);
   423           // normalize own velocity
   424           velX = (velX / velLength) * Q;
   425           velY = (velY / velLength) * Q;
   426           velZ = (velZ / velLength) * Q;
   428           accX += velX2;
   429           accY += velY2;
   430           accZ += velZ2;
   432           accX2 += velX;
   433           accY2 += velY;
   434           accZ2 += velZ;
   435         }
   437         if (distSqrd > attract) {        //attract
   438           var threshDelta2 = 1 - align;
   439           var adjustedPercent2 = (percent - align) / threshDelta2;
   440           var C = (1 - (Math.cos(adjustedPercent2 * 3.14159265 * 2) * 0.5 + 0.5)) * attractPower;
   442           // normalize the distance vector
   443           var dx = (rx / (length)) * C;
   444           var dy = (ry / (length)) * C;
   445           var dz = (rz / (length)) * C;
   447           debug = 1.1;
   449           accX += dx;
   450           accY += dy;
   451           accZ += dz;
   453           accX2 -= dx;
   454           accY2 -= dy;
   455           accZ2 -= dz;
   456         }
   457       }
   458     }
   460     // enforce speed limits
   461     if (time > 500) {
   462       var accSquared = accX * accX + accY * accY + accZ * accZ;
   463       if (accSquared > speedLimit) {
   464         accX = accX * .015;
   465         accY = accY * .015;
   466         accZ = accZ * .015;
   467       }
   469       var accSquared2 = accX2 * accX2 + accY2 * accY2 + accZ2 * accZ2;
   470       if (accSquared2 > speedLimit) {
   471         accX2 = accX2 * .015;
   472         accY2 = accY2 * .015;
   473         accZ2 = accZ2 * .015;
   474       }
   475     }
   477     // Caclulate new velocity
   478     newX = vel[index][0] + accX;
   479     newY = vel[index][1] + accY;
   480     newZ = vel[index][2] + accZ;
   482     newX2 = vel[index][3] + accX2;
   483     newY2 = vel[index][4] + accY2;
   484     newZ2 = vel[index][5] + accZ2;
   486     if (time < 500) {
   487       var acs = newX2 * newX2 + newY2 * newY2 + newZ2 * newZ2;
   488       if (acs > speedLimit) {
   489         newX2 = newX2 * .15;
   490         newY2 = newY2 * .15;
   491         newZ2 = newZ2 * .15;
   492       }
   494       var acs2 = newX * newX + newY * newY + newZ * newZ;
   495       if (acs2 > speedLimit) {
   496         newX = newX * .15;
   497         newY = newY * .15;
   498         newZ = newZ * .15;
   499       }
   500     }
   502     return [newX, newY, newZ, newX2, newY2, newZ2];
   503   },
   505   positionSeq: function positionSeq(index) {
   506     var vel = NBody.private.vel;
   507     var pos = NBody.private.pos;
   509     var x = 0;
   510     var y = 0;
   511     var z = 0;
   513     var velX = vel[index][0];
   514     var velY = vel[index][1];
   515     var velZ = vel[index][2];
   517     var velX2 = vel[index][3];
   518     var velY2 = vel[index][4];
   519     var velZ2 = vel[index][5];
   521     var netX = (velX - velX2);
   522     var netY = (velY - velY2);
   523     var netZ = (velZ - velZ2);
   525     x = pos[index][0] + netX;
   526     y = pos[index][1] + netY;
   527     z = pos[index][2] + netZ;
   529     return [x, y, z];
   530   }
   531 };
   533 function emulateNBody(mode, numBodies, ticks) {
   534   NBody.init(mode, numBodies);
   535   for (var i = 0; i < ticks; i++) {
   536     var start = Date.now();
   537     if (mode === "par")
   538       NBody.tickPar();
   539     else
   540       NBody.tickSeq();
   541     //print(NBody.private.pos);
   542     print(mode + " bodies=" + numBodies + " tick=" + (i+1) + "/" + ticks + ": " + (Date.now() - start) + " ms");
   543   }
   544 }
   546 // Using 4000 bodies going off Rick's comment as 4000 being a typical workload.
   547 const NUMBODIES = 4000;
   548 const TICKS = 10;
   550 Math.seedrandom("seed");
   552 benchmark("NBODY", 1, DEFAULT_MEASURE,
   553           function () { emulateNBody("seq", NUMBODIES, TICKS); },
   554           function () { emulateNBody("par", NUMBODIES, TICKS); });

mercurial