Skip to content

Commit

Permalink
Add SIMD version of NBody benchmark test
Browse files Browse the repository at this point in the history
no-SIMD version has been refactored
  • Loading branch information
GorogPeter committed Oct 8, 2023
1 parent 0125945 commit fef3850
Show file tree
Hide file tree
Showing 3 changed files with 288 additions and 93 deletions.
7 changes: 4 additions & 3 deletions test/wasmBenchmarker/benchmark.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,18 +37,19 @@
"huffman": 0,
"k_nucleotide": 1,
"mandelbrot": 775007,
"nbody": -0.169083713,
"nbody": -0.1691057,
"nqueens": 0,
"prime": 48611,
"quick_sort": 0,
"red-black": 4000000,
"salesman": 840,
"simdMandelbrot": 775007
"simdMandelbrot": 775007,
"simdNbody": -0.1691057
}
# https://benchmarksgame-team.pages.debian.net/benchmarksgame/description/simple.html#simple
gameTests = ["mandelbrot", "nbody", "gregory", "fannkuch", "k_nucleotide"]

simdTests = ["simdMandelbrot"]
simdTests = ["simdMandelbrot", "simdNbody"]

def prepare_arg_pars():
parser = argparse.ArgumentParser()
Expand Down
195 changes: 105 additions & 90 deletions test/wasmBenchmarker/ctests/nbody.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,150 +15,165 @@
*/

#include <stdio.h>
#include <math.h>

#define LOOP 200000
#define SOLAR_MASS 39.47841760435743
#define DAYS_PER_YEAR 365.24
#define LOOP 450000
#define SOLAR_MASS 39.47841760435743f
#define DAYS_PER_YEAR 365.24f
#define BODIES_COUNT 5
#define INTERACTIONS_COUNT (BODIES_COUNT * (BODIES_COUNT - 1) / 2)

#define square(x) x * x

typedef struct {
double position[3], velocity[3], mass;
float position[3];
float velocity[3];
float mass;
} body;

body solarBodies[] = {
{// Sun
.mass = SOLAR_MASS
},
{// Jupiter
{4.84143144246472090e+00, -1.16032004402742839e+00, -1.03622044471123109e-01},
{1.66007664274403694e-03 * DAYS_PER_YEAR, 7.69901118419740425e-03 * DAYS_PER_YEAR,
-6.90460016972063023e-05 *
DAYS_PER_YEAR},
9.54791938424326609e-04 * SOLAR_MASS
},
{// Saturn
{8.34336671824457987e+00, 4.12479856412430479e+00, -4.03523417114321381e-01},
{-2.76742510726862411e-03 * DAYS_PER_YEAR, 4.99852801234917238e-03 *
DAYS_PER_YEAR, 2.30417297573763929e-05 *
DAYS_PER_YEAR},
2.85885980666130812e-04 * SOLAR_MASS
},
{// Uranus
{1.28943695621391310e+01, -1.51111514016986312e+01, -2.23307578892655734e-01},
{2.96460137564761618e-03 * DAYS_PER_YEAR, 2.37847173959480950e-03 *
DAYS_PER_YEAR, -2.96589568540237556e-05 *
DAYS_PER_YEAR},
4.36624404335156298e-05 * SOLAR_MASS
},
{// Neptune
{1.53796971148509165e+01, -2.59193146099879641e+01, 1.79258772950371181e-01},
{2.68067772490389322e-03 * DAYS_PER_YEAR, 1.62824170038242295e-03 *
DAYS_PER_YEAR, -9.51592254519715870e-05 *
DAYS_PER_YEAR},
5.15138902046611451e-05 * SOLAR_MASS
}
};

double square_root(double x) {
int square;
int p = 0;

do {
p++;
square = (p + 1) * (p + 1);
} while (x > square);

double y = (double) p;
int c = 0;

while (c < 10) {
y = (x / y + y) / 2;

if (y * y == x) {
return y;
}

c++;
}

return y;
}

void move() {
double dPosition[3][INTERACTIONS_COUNT], magnitudes[INTERACTIONS_COUNT];
void move(body solarBodies[]) {
float dPosition[INTERACTIONS_COUNT][3];
float magnitudes[INTERACTIONS_COUNT];

for (unsigned int i = 0, k = 0; i < BODIES_COUNT - 1; i++) {
for (unsigned int j = i + 1; j < BODIES_COUNT; j++, k++) {
for (unsigned int m = 0; m < 3; m++) {
dPosition[m][k] = solarBodies[i].position[m] - solarBodies[j].position[m];
dPosition[k][m] = solarBodies[i].position[m] - solarBodies[j].position[m];
}
}
}

for (unsigned int i = 0; i < INTERACTIONS_COUNT; i++) {
const double dx = dPosition[0][i];
const double dy = dPosition[1][i];
const double dz = dPosition[2][i];
const double distanceSquared = dx * dx + dy * dy + dz * dz;
magnitudes[i] = 0.01 / (square_root(distanceSquared) * distanceSquared);
const float dx = dPosition[i][0];
const float dy = dPosition[i][1];
const float dz = dPosition[i][2];
const float distanceSquared = square(dx) + square(dy) + square(dz);
magnitudes[i] = 0.01f / (sqrtf(distanceSquared) * distanceSquared);
}

for (unsigned int i = 0, k = 0; i < BODIES_COUNT - 1; i++) {
for (unsigned int j = i + 1; j < BODIES_COUNT; j++, k++) {
const double massI = solarBodies[i].mass * magnitudes[k];
const double massJ = solarBodies[j].mass * magnitudes[k];
const float massI = solarBodies[i].mass * magnitudes[k];
const float massJ = solarBodies[j].mass * magnitudes[k];

for (unsigned int m = 0; m < 3; ++m) {
solarBodies[i].velocity[m] -= dPosition[m][k] * massJ;
solarBodies[j].velocity[m] += dPosition[m][k] * massI;
for (unsigned int m = 0; m < 3; m++) {
solarBodies[i].velocity[m] -= dPosition[k][m] * massJ;
solarBodies[j].velocity[m] += dPosition[k][m] * massI;
}
}
}

for (unsigned int i = 0; i < BODIES_COUNT; i++) {
for (unsigned int m = 0; m < 3; m++) {
solarBodies[i].position[m] += 0.01 * solarBodies[i].velocity[m];
solarBodies[i].position[m] += 0.01f * solarBodies[i].velocity[m];
}
}
}

double energy() {
double energy = 0.0;
float energy(body solarBodies[]) {
float energy = 0.0f;

for (unsigned int i = 0; i < BODIES_COUNT; i++) {
energy += 0.5 * solarBodies[i].mass *
energy += 0.5f * solarBodies[i].mass *
(solarBodies[i].velocity[0] * solarBodies[i].velocity[0] +
solarBodies[i].velocity[1] * solarBodies[i].velocity[1] +
solarBodies[i].velocity[2] * solarBodies[i].velocity[2]);

for (unsigned int j = i + 1; j < BODIES_COUNT; j++) {
double dx = solarBodies[i].position[0] - solarBodies[j].position[0];
double dy = solarBodies[i].position[1] - solarBodies[j].position[1];
double dz = solarBodies[i].position[2] - solarBodies[j].position[2];
double distance = square_root(dx * dx + dy * dy + dz * dz);
float dx = solarBodies[i].position[0] - solarBodies[j].position[0];
float dy = solarBodies[i].position[1] - solarBodies[j].position[1];
float dz = solarBodies[i].position[2] - solarBodies[j].position[2];
float distance = sqrtf(square(dx) + square(dy) + square(dz));
energy -= (solarBodies[i].mass * solarBodies[j].mass) / distance;
}
}

return energy;
}

double runtime() {
for (unsigned int i = 0; i < BODIES_COUNT; ++i) {
for (unsigned int m = 0; m < 3; ++m) {
float runtime() {
body solarBodies[] = {
{ // Sun
.position = {
0.0f,
0.0f,
0.0f
},
.velocity = {
0.0f,
0.0f,
0.0f
},
.mass = SOLAR_MASS
},
{ // Jupiter
.position = {
+4.84143144246472090e+00f,
-1.16032004402742839e+00f,
-1.03622044471123109e-01f
},
.velocity = {
+1.66007664274403694e-03f * DAYS_PER_YEAR,
+7.69901118419740425e-03f * DAYS_PER_YEAR,
-6.90460016972063023e-05f * DAYS_PER_YEAR,
},
.mass = +9.54791938424326609e-04f * SOLAR_MASS
},
{ // Saturn
.position = {
+8.34336671824457987e+00f,
+4.12479856412430479e+00f,
-4.03523417114321381e-01f
},
.velocity = {
-2.76742510726862411e-03f * DAYS_PER_YEAR,
+4.99852801234917238e-03f * DAYS_PER_YEAR,
+2.30417297573763929e-05f * DAYS_PER_YEAR
},
.mass = +2.85885980666130812e-04f * SOLAR_MASS
},
{ // Uranus
.position = {
+1.28943695621391310e+01f,
-1.51111514016986312e+01f,
-2.23307578892655734e-01f
},
.velocity = {
+2.96460137564761618e-03f * DAYS_PER_YEAR,
+2.37847173959480950e-03f * DAYS_PER_YEAR,
-2.96589568540237556e-05f * DAYS_PER_YEAR
},
.mass = +4.36624404335156298e-05f * SOLAR_MASS
},
{ // Neptune
.position = {
+1.53796971148509165e+01f,
-2.59193146099879641e+01f,
+1.79258772950371181e-01f
},
.velocity = {
+2.68067772490389322e-03f * DAYS_PER_YEAR,
+1.62824170038242295e-03f * DAYS_PER_YEAR,
-9.51592254519715870e-05f * DAYS_PER_YEAR
},
.mass = +5.15138902046611451e-05f * SOLAR_MASS
}
};

for (unsigned int i = 0; i < BODIES_COUNT; i++) {
for (unsigned int m = 0; m < 3; m++) {
solarBodies[0].velocity[m] -= solarBodies[i].velocity[m] * solarBodies[i].mass / SOLAR_MASS;
}
}

for (unsigned int i = 0; i < LOOP; i++) {
move();
move(solarBodies);
}

return energy();
return energy(solarBodies);
}

int main() {
printf("%.9f\n", runtime());
return 0;
}
}
Loading

0 comments on commit fef3850

Please sign in to comment.