Skip to content

Add content on performance benchmarks. #461

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 25 commits into from
Closed
Show file tree
Hide file tree
Changes from 21 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
7f13511
Add benchmark-doc, codes and graph
khushi-411 Aug 11, 2021
fb713be
Modified the graph, table, and code for visualization.
khushi-411 Aug 11, 2021
22f6dca
Modified Visulization and documentation.
khushi-411 Aug 13, 2021
0684e21
Minor Correction (name of the graph)
khushi-411 Aug 13, 2021
83e7d46
Plotted different type of visualization, added links to web page
khushi-411 Aug 15, 2021
467daf6
Minor Correction in content/en/benchmark.md
khushi-411 Aug 15, 2021
57a3221
Increased the size of the label in the graph.
khushi-411 Aug 15, 2021
3450f43
Reformatted number of characters in lines to <80 characters
khushi-411 Aug 17, 2021
7939706
Optimized NumPy Code, and Pythran code, Removed unnecessary files.
khushi-411 Aug 26, 2021
17b8095
Added pure-python code, renamed numpy file, deleted unnecessary files.
khushi-411 Aug 31, 2021
8342aa2
Optimized codes, modified content for the web page.
khushi-411 Sep 5, 2021
b19857d
modified codes, now the code outputsthe same results via different im…
khushi-411 Sep 7, 2021
258b22b
update codes and add updated plot.
khushi-411 Sep 9, 2021
a496e53
Modified codes to maintain uniformity and used Python operators rathe…
khushi-411 Sep 11, 2021
9e19e0d
Add Single implementation of compiled methods, made correction in C++…
khushi-411 Sep 16, 2021
0c0e6b5
Improved Documentation
khushi-411 Sep 18, 2021
c420d50
Changed Graph, made minor typo corrections in the documentation and u…
khushi-411 Sep 18, 2021
bf0f84d
Minor correction
khushi-411 Sep 18, 2021
b70655c
Minor correction
khushi-411 Sep 20, 2021
4f5e88f
Graph Modification
khushi-411 Sep 24, 2021
6a9a2d7
Changed the color of the bar in Graph.
khushi-411 Sep 28, 2021
33cf330
Reformated statements.
khushi-411 Sep 29, 2021
a823681
Change plot
khushi-411 Sep 30, 2021
71e4876
Deleted files
khushi-411 Sep 30, 2021
d384579
edit content
khushi-411 Oct 1, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
170 changes: 170 additions & 0 deletions benchmarks/cpp/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
#include <iostream>
#include <math.h>
#include <numeric>
#include <vector>

typedef double real;
using namespace std;

class Star {
public:
real m;
vector<real> r;
vector<real> v;
vector<real> a, a0;

Star() {
r.assign(3, 0);
v.assign(3, 0);
a.assign(3, 0);
a0.assign(3, 0);
}

Star(real mass, vector<real> pos, vector<real> vel) {
m = mass;
r = pos;
v = vel;
}

friend ostream &operator<<(ostream &so, const Star &si) {
so << si.m << " " << si.r[0] << " " << si.r[1] << " " << si.r[2] << " "
<< si.v[0] << " " << si.v[1] << " " << si.v[2] << endl;
return so;
}
};

class Cluster : public Star {
protected:
public:
vector<Star> s;
Cluster() : Star() {}

void acceleration() {
for (vector<Star>::iterator si = s.begin(); si != s.end(); ++si)
si->a.assign(3, 0);

for (vector<Star>::iterator si = s.begin(); si != s.end(); ++si) {
vector<real> rij(3);
real init = 0.0;

for (vector<Star>::iterator sj = s.begin(); sj != s.end(); ++sj) {
if (si != sj) {

for (int i = 0; i != 3; ++i)
rij[i] = si->r[i] - sj->r[i];

real RdotR = inner_product(rij.begin(), rij.end(), rij.begin(), init);
real apre = 1. / sqrt(RdotR * RdotR * RdotR);

for (int i = 0; i != 3; ++i) {
si->a[i] = sj->m * -1 * apre * rij[i];
}
}
}
}
}

void updatePositions(real dt) {
for (vector<Star>::iterator si = s.begin(); si != s.end(); ++si) {
si->a0 = si->a;
for (int i = 0; i != 3; ++i)
si->r[i] += dt * si->v[i] + 0.5 * dt * dt * si->a0[i];
}
}

void updateVelocities(real dt) {

for (vector<Star>::iterator si = s.begin(); si != s.end(); ++si) {
for (int i = 0; i != 3; ++i)
si->v[i] += 0.5 * dt * (si->a0[i] + si->a[i]);
si->a0 = si->a;
}
}

vector<real> energies() {
real init = 0;
vector<real> E(3), rij(3);
E.assign(3, 0);

for (vector<Star>::iterator si = s.begin(); si != s.end(); ++si)
E[1] += 0.5 * si->m *
inner_product(si->v.begin(), si->v.end(), si->v.begin(), init);

// Potential energy
for (vector<Star>::iterator si = s.begin(); si != s.end(); ++si) {
for (vector<Star>::iterator sj = si + 1; sj != s.end(); ++sj) {
for (int i = 0; i != 3; ++i)
rij[i] = si->r[i] - sj->r[i];
E[2] -= si->m * sj->m /
sqrt(inner_product(rij.begin(), rij.end(), rij.begin(), init));
}
}
E[0] = E[1] + E[2];
return E;
}

// Print function
friend ostream &operator<<(ostream &so, Cluster &cl) {
for (vector<Star>::iterator si = cl.s.begin(); si != cl.s.end(); ++si)
so << *si;
return so;
}
};

int main(int argc, char* argv[]) {

Cluster cl;
real m;
int dummy;
vector<real> r(3), v(3);

// Read input data from the command line (makeplummer | dumbp)
do {
cin >> dummy;
cin >> m;
for (int i = 0; i != 3; ++i)
cin >> r[i];
for (int i = 0; i != 3; ++i)
cin >> v[i];
cl.s.push_back(Star(m, r, v));
} while (!cin.eof());

cl.s.pop_back();

// Compute initial energu of the system
vector<real> E(3), E0(3);
E0 = cl.energies();

// Start time, end time and simulation step
real t = 0.0;
real tend;

if (argc > 1)
tend = strtod(argv[1], NULL);
else
tend = 10.0;

real dt = 1e-3;
int k = 0;

for (int i = 0; i < 50; i++) {
cl.acceleration();

while (t < tend) {
cl.updatePositions(dt);

cl.acceleration();

cl.updateVelocities(dt);

t += dt;
k += 1;
if (k % 100 == 0) {
E = cl.energies();
}
}
t = 0;
}

return 0;
}
6 changes: 6 additions & 0 deletions benchmarks/data/table.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
,32,64,128,256
NumPy,13.880000000000001,15.59,17.899999999999999,18.27
Python,26.82,50.130000000000003,105.01000000000001,178.59999999999999
C++,3.206,5.7249999999999996,11.44,19.43
Numba,3.2229999999999999,6.5209999999999999,13.640000000000001,26.640000000000001
Pythran,0.65910000000000002,1.2810999999999999,2.5082,5.2042000000000002
108 changes: 108 additions & 0 deletions benchmarks/python/compiled_methods.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
import sys
import math
import timeit

import numpy as np
import pandas as pd

from transonic import jit

def load_input_data(path):

df = pd.read_csv(
path, names = ["mass", "x", "y", "z", "vx", "vy", "vz"], delimiter=r"\s+"
)

masses = df["mass"].values.copy()
positions = df.loc[:, ["x", "y", "z"]].values.copy()
velocities = df.loc[:, ["vx", "vy", "vz"]].values.copy()

return masses, positions, velocities

def compute_accelerations(accelerations, masses, positions):
nb_particles = masses.size

for index_p0 in range(nb_particles - 1):
position0 = positions[index_p0]
mass0 = masses[index_p0]

# TODO: Use compiled methods like Numba & Pythran in vectorized approach.
# Issue: https://github.com/khushi-411/numpy-benchmarks/issues/4
for index_p1 in range(index_p0 + 1, nb_particles):
mass1 = masses[index_p1]

vectors = position0 - positions[index_p1]

distances = (vectors**2).sum()
coefs = 1./distances**1.5

accelerations[index_p0] += mass1 * -1 * vectors * coefs
accelerations[index_p1] += mass0 * vectors * coefs

return accelerations

@jit
def loop(
time_step, nb_steps, masses, positions,
velocities):

accelerations = np.zeros_like(positions)
accelerations1 = np.zeros_like(positions)

accelerations = compute_accelerations(accelerations, masses, positions)

time = 0.0
energy0, _, _ = compute_energies(masses, positions, velocities)
energy_previous = energy0

for step in range(nb_steps):
positions += time_step*velocities + 0.5*accelerations*time_step**2

accelerations, accelerations1 = accelerations1, accelerations
accelerations.fill(0)
accelerations = compute_accelerations(accelerations, masses, positions)

velocities += 0.5*time_step*(accelerations+accelerations1)

time += time_step

if not step % 100:
energy, _, _ = compute_energies(masses, positions, velocities)
energy_previous = energy

return energy, energy0

def compute_energies(masses, positions, velocities):

ke = 0.5 * masses @ np.sum(velocities**2, axis=1)

nb_particles = masses.size
pe = 0.0
for index_p0 in range(nb_particles - 1):

mass0 = masses[index_p0]
for index_p1 in range(index_p0 + 1, nb_particles):

mass1 = masses[index_p1]
vector = positions[index_p0] - positions[index_p1]

distance = math.sqrt((vector**2).sum())

pe -= (mass0*mass1) / distance**2

return ke+pe, ke, pe

if __name__ == "__main__":

try:
time_end = float(sys.argv[2])
except IndexError:
time_end = 10.0

time_step = 0.001
nb_steps = int(time_end/time_step) + 1

path_input = sys.argv[1]
masses, positions, velocities = load_input_data(path_input)

print('time taken:', timeit.timeit('loop(time_step, nb_steps, masses, positions, velocities)', globals=globals(), number=50))
105 changes: 105 additions & 0 deletions benchmarks/python/numpy_python.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
import sys
import math
import timeit

import numpy as np
import pandas as pd

def load_input_data(path):

df = pd.read_csv(
path, names = ["mass", "x", "y", "z", "vx", "vy", "vz"], delimiter=r"\s+"
)

masses = df["mass"].values.copy()
positions = df.loc[:, ["x", "y", "z"]].values.copy()
velocities = df.loc[:, ["vx", "vy", "vz"]].values.copy()

return masses, positions, velocities

def compute_accelerations(accelerations, masses, positions):
nb_particles = masses.size

for index_p0 in range(nb_particles - 1):
position0 = positions[index_p0]
mass0 = masses[index_p0]

vectors = position0 - positions[index_p0 + 1: nb_particles]

distances = (vectors**2).sum(axis=1)
coefs = 1./distances**1.5

accelerations[index_p0] += np.sum((masses[index_p0 + 1: nb_particles] * -1 * vectors.T * coefs).T, axis=0)
accelerations[index_p0 + 1: nb_particles] += (mass0 * vectors.T * coefs).T

return accelerations

def numpy_loop(
time_step: float,
nb_steps: int,
masses: "float[]",
positions: "float[:,:]",
velocities: "float[:,:]",
):

accelerations = np.zeros_like(positions)
accelerations1 = np.zeros_like(positions)

accelerations = compute_accelerations(accelerations, masses, positions)

time = 0.0

energy0, _, _ = compute_energies(masses, positions, velocities)
energy_previous = energy0

for step in range(nb_steps):
positions += time_step*velocities + 0.5*accelerations*time_step**2

accelerations, accelerations1 = accelerations1, accelerations
accelerations.fill(0)
accelerations = compute_accelerations(accelerations, masses, positions)

velocities += 0.5*time_step*(accelerations+accelerations1)

time += time_step

if not step%100:
energy, _, _ = compute_energies(masses, positions, velocities)
energy_previous = energy

return energy, energy0

def compute_energies(masses, positions, velocities):

ke = 0.5 * masses @ np.sum(velocities**2, axis=1)

nb_particles = masses.size
pe = 0.0
for index_p0 in range(nb_particles - 1):

mass0 = masses[index_p0]
for index_p1 in range(index_p0 + 1, nb_particles):

mass1 = masses[index_p1]
vector = positions[index_p0] - positions[index_p1]

distance = math.sqrt((vector**2).sum())

pe -= (mass0*mass1) / distance**2

return ke+pe, ke, pe

if __name__ == "__main__":

try:
time_end = float(sys.argv[2])
except IndexError:
time_end = 10.0

time_step = 0.001
nb_steps = int(time_end/time_step) + 1

path_input = sys.argv[1]
masses, positions, velocities = load_input_data(path_input)

print('time taken:', timeit.timeit('numpy_loop(time_step, nb_steps, masses, positions, velocities)', globals=globals(), number=50))
Loading