Skip to content

Commit a496e53

Browse files
committed
Modified codes to maintain uniformity and used Python operators rather than NumPy's operators at the required places.
1 parent 258b22b commit a496e53

File tree

5 files changed

+69
-116
lines changed

5 files changed

+69
-116
lines changed

benchmarks/cpp/main.cpp

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ class Cluster : public Star {
5757
real apre = 1. / sqrt(RdotR * RdotR * RdotR);
5858

5959
for (int i = 0; i != 3; ++i) {
60-
si->a[i] -= sj->m * apre * rij[i];
60+
si->a[i] = sj->m * -1 * apre * rij[i];
6161
}
6262
}
6363
}
@@ -148,23 +148,22 @@ int main(int argc, char* argv[]) {
148148
int k = 0;
149149

150150
for (int i = 0; i < 50; i++) {
151-
cl.acceleration();
152-
153-
while (t < tend) {
151+
cl.acceleration();
154152

155-
cl.updatePositions(dt);
153+
while (t < tend) {
154+
cl.updatePositions(dt);
156155

157-
cl.acceleration();
156+
cl.acceleration();
158157

159-
cl.updateVelocities(dt);
158+
cl.updateVelocities(dt);
160159

161-
t += dt;
162-
k += 1;
163-
if (k % 100 == 0) {
164-
E = cl.energies();
160+
t += dt;
161+
k += 1;
162+
if (k % 100 == 0) {
163+
E = cl.energies();
164+
}
165165
}
166166
}
167-
}
168167

169168
return 0;
170169
}

benchmarks/python/acc_numba.py

Lines changed: 14 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -30,28 +30,12 @@ def compute_accelerations(accelerations, masses, positions):
3030

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

33-
distances = np.square(vectors).sum(axis = 1)
34-
coefs = distances ** 1.5
35-
36-
_x = np.add(np.sum(
37-
np.divide(
38-
np.multiply(
39-
masses[index_p0 + 1: nb_particles], -1 * vectors.T
40-
),
41-
coefs).T, axis = 0),
42-
accelerations[index_p0]
43-
)
44-
accelerations[index_p0] = _x
45-
46-
_temp = np.add(
47-
np.divide(
48-
np.multiply(
49-
mass0, vectors.T
50-
),
51-
coefs).T,
52-
accelerations[index_p0 + 1: nb_particles]
53-
)
54-
accelerations[index_p0 + 1: nb_particles] = _temp
33+
distances = (vectors**2).sum(axis=1)
34+
coefs = 1./distances**1.5
35+
36+
accelerations[index_p0] += np.sum((masses[index_p0 + 1: nb_particles] * -1 * vectors.T * coefs), axis=0)
37+
38+
accelerations[index_p0 + 1: nb_particles] += (mass0 * vectors.T * coefs).T
5539

5640
return accelerations
5741

@@ -74,13 +58,13 @@ def numba_loop(
7458
energy_previous = energy0
7559

7660
for step in range(nb_steps):
77-
positions = sum(np.multiply(velocities, time_step), 0.5 * np.multiply(accelerations, time_step ** 2)) + positions
61+
positions += time_step*velocities + 0.5*accelerations*time_step**2
7862

7963
accelerations, accelerations1 = accelerations1, accelerations
8064
accelerations.fill(0)
8165
accelerations = compute_accelerations(accelerations, masses, positions)
8266

83-
velocities = 0.5 * np.multiply(time_step, np.add(accelerations, accelerations1)) + velocities
67+
velocities += 0.5*time_step*(accelerations+accelerations1)
8468

8569
time += time_step
8670

@@ -93,24 +77,23 @@ def numba_loop(
9377
@jit
9478
def compute_energies(masses, positions, velocities):
9579

96-
ke = 0.5 * (np.multiply(masses, np.square(velocities).sum(axis = 1)).sum())
80+
ke = 0.5 * np.sum(masses * np.sum(velocities**2, axis=1))
9781

9882
nb_particles = masses.size
99-
10083
pe = 0.0
10184
for index_p0 in range(nb_particles - 1):
85+
10286
mass0 = masses[index_p0]
103-
10487
for index_p1 in range(index_p0 + 1, nb_particles):
10588

10689
mass1 = masses[index_p1]
10790
vector = positions[index_p0] - positions[index_p1]
10891

109-
distance = np.sqrt((vector ** 2).sum())
92+
distance = math.sqrt((vector**2).sum())
11093

111-
pe = np.subtract(np.divide(np.multiply(mass0, mass1), np.square(distance)), pe)
94+
pe -= (mass0*mass1) / distance**2
11295

113-
return ke + pe, ke, pe
96+
return ke+pe, ke, pe
11497

11598
if __name__ == "__main__":
11699

@@ -125,4 +108,4 @@ def compute_energies(masses, positions, velocities):
125108
path_input = sys.argv[1]
126109
masses, positions, velocities = load_input_data(path_input)
127110

128-
print('time taken:', timeit.timeit('numba_loop(time_step, nb_steps, masses, positions, velocities)', globals = globals(), number = 50))
111+
print('time taken:', timeit.timeit('numba_loop(time_step, nb_steps, masses, positions, velocities)', globals=globals(), number=50))

benchmarks/python/acc_pythran.py

Lines changed: 15 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -26,33 +26,23 @@ def compute_accelerations(accelerations, masses, positions):
2626
position0 = positions[index_p0]
2727
mass0 = masses[index_p0]
2828

29-
vector = np.empty(3)
30-
3129
for index_p1 in range(index_p0 + 1, nb_particles):
3230
mass1 = masses[index_p1]
33-
position1 = positions[index_p1]
3431

35-
for i in range(3):
36-
vector[i] = position0[i] - position1[i]
32+
vectors = position0 - positions[index_p1]
3733

38-
distance = sum(vector ** 2) * math.sqrt(sum(vector ** 2))
39-
coef_m1 = mass0 / distance
40-
coef_m2 = mass1 / distance
34+
distances = (vectors**2).sum()
35+
coefs = 1./distances**1.5
4136

42-
for i in range(3):
43-
accelerations[index_p0][i] += coef_m1 * -1 * vector[i]
44-
accelerations[index_p1][i] += coef_m2 * vector[i]
37+
accelerations[index_p0] += mass1 * -1 * vectors * coefs
38+
accelerations[index_p1] += mass0 * vectors * coefs
4539

4640
return accelerations
4741

4842
@jit
4943
def pythran_loop(
50-
time_step: float,
51-
nb_steps: int,
52-
masses: "float[]",
53-
positions: "float[:,:]",
54-
velocities: "float[:,:]",
55-
):
44+
time_step, nb_steps, masses, positions,
45+
velocities):
5646

5747
accelerations = np.zeros_like(positions)
5848
accelerations1 = np.zeros_like(positions)
@@ -64,13 +54,13 @@ def pythran_loop(
6454
energy_previous = energy0
6555

6656
for step in range(nb_steps):
67-
positions = sum(np.multiply(velocities, time_step), 0.5 * np.multiply(accelerations, time_step ** 2)) + positions
57+
positions += time_step*velocities + 0.5*accelerations*time_step**2
6858

6959
accelerations, accelerations1 = accelerations1, accelerations
7060
accelerations.fill(0)
7161
accelerations = compute_accelerations(accelerations, masses, positions)
7262

73-
velocities = 0.5 * np.multiply(time_step, np.add(accelerations, accelerations1)) + velocities
63+
velocities += 0.5*time_step*(accelerations+accelerations1)
7464

7565
time += time_step
7666

@@ -82,24 +72,23 @@ def pythran_loop(
8272

8373
def compute_energies(masses, positions, velocities):
8474

85-
ke = 0.5 * (np.multiply(masses, np.square(velocities).sum(axis = 1)).sum())
75+
ke = 0.5 * np.sum(masses * np.sum(velocities**2, axis=1))
8676

8777
nb_particles = masses.size
88-
8978
pe = 0.0
9079
for index_p0 in range(nb_particles - 1):
91-
mass0 = masses[index_p0]
9280

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

9584
mass1 = masses[index_p1]
9685
vector = positions[index_p0] - positions[index_p1]
9786

98-
distance = np.sqrt((vector ** 2).sum())
87+
distance = math.sqrt((vector**2).sum())
9988

100-
pe = np.subtract(np.divide(np.multiply(mass0, mass1), np.square(distance)), pe)
89+
pe -= (mass0*mass1) / distance**2
10190

102-
return ke + pe, ke, pe
91+
return ke+pe, ke, pe
10392

10493
if __name__ == "__main__":
10594

@@ -114,4 +103,4 @@ def compute_energies(masses, positions, velocities):
114103
path_input = sys.argv[1]
115104
masses, positions, velocities = load_input_data(path_input)
116105

117-
print('time taken:', timeit.timeit('pythran_loop(time_step, nb_steps, masses, positions, velocities)', globals = globals(), number = 50))
106+
print('time taken:', timeit.timeit('pythran_loop(time_step, nb_steps, masses, positions, velocities)', globals=globals(), number=50))

benchmarks/python/optimized-numpy.py

Lines changed: 14 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
def load_input_data(path):
99

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

1414
masses = df["mass"].values.copy()
@@ -26,28 +26,11 @@ def compute_accelerations(accelerations, masses, positions):
2626

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

29-
distances = np.square(vectors).sum(axis = 1)
30-
coefs = distances ** 1.5
31-
32-
_x = np.add(np.sum(
33-
np.divide(
34-
np.multiply(
35-
masses[index_p0 + 1: nb_particles], -1 * vectors.T
36-
),
37-
coefs).T, axis = 0),
38-
accelerations[index_p0]
39-
)
40-
accelerations[index_p0] = _x
41-
42-
_temp = np.add(
43-
np.divide(
44-
np.multiply(
45-
mass0, vectors.T
46-
),
47-
coefs).T,
48-
accelerations[index_p0 + 1: nb_particles]
49-
)
50-
accelerations[index_p0 + 1: nb_particles] = _temp
29+
distances = (vectors**2).sum(axis=1)
30+
coefs = 1./distances**1.5
31+
32+
accelerations[index_p0] += np.sum((masses[index_p0 + 1: nb_particles] * -1 * vectors.T * coefs), axis=0)
33+
accelerations[index_p0 + 1: nb_particles] += (mass0 * vectors.T * coefs).T
5134

5235
return accelerations
5336

@@ -70,28 +53,27 @@ def numpy_loop(
7053
energy_previous = energy0
7154

7255
for step in range(nb_steps):
73-
positions = sum(np.multiply(velocities, time_step), 0.5 * np.multiply(accelerations, time_step ** 2)) + positions
56+
positions += time_step*velocities + 0.5*accelerations*time_step**2
7457

7558
accelerations, accelerations1 = accelerations1, accelerations
7659
accelerations.fill(0)
7760
accelerations = compute_accelerations(accelerations, masses, positions)
7861

79-
velocities = 0.5 * np.multiply(time_step, np.add(accelerations, accelerations1)) + velocities
62+
velocities += 0.5*time_step*(accelerations+accelerations1)
8063

8164
time += time_step
8265

83-
if not step % 100:
66+
if not step%100:
8467
energy, _, _ = compute_energies(masses, positions, velocities)
8568
energy_previous = energy
8669

8770
return energy, energy0
8871

8972
def compute_energies(masses, positions, velocities):
9073

91-
ke = 0.5 * (np.multiply(masses, np.square(velocities).sum(axis = 1)).sum())
74+
ke = 0.5 * np.sum(masses * np.sum(velocities**2, axis=1))
9275

9376
nb_particles = masses.size
94-
9577
pe = 0.0
9678
for index_p0 in range(nb_particles - 1):
9779

@@ -101,11 +83,11 @@ def compute_energies(masses, positions, velocities):
10183
mass1 = masses[index_p1]
10284
vector = positions[index_p0] - positions[index_p1]
10385

104-
distance = np.sqrt((vector ** 2).sum())
86+
distance = math.sqrt((vector**2).sum())
10587

106-
pe = np.subtract(np.divide(np.multiply(mass0, mass1), np.square(distance)), pe)
88+
pe -= (mass0*mass1) / distance**2
10789

108-
return ke + pe, ke, pe
90+
return ke+pe, ke, pe
10991

11092
if __name__ == "__main__":
11193

@@ -120,4 +102,4 @@ def compute_energies(masses, positions, velocities):
120102
path_input = sys.argv[1]
121103
masses, positions, velocities = load_input_data(path_input)
122104

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

0 commit comments

Comments
 (0)