Skip to content

Commit 8e559d6

Browse files
authored
simd version of nbody bench for Odin (#360)
1 parent 55a05b7 commit 8e559d6

File tree

2 files changed

+164
-0
lines changed

2 files changed

+164
-0
lines changed

bench/algorithm/nbody/1-i.odin

Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
// contributed by Branimir Maksimovic
2+
3+
package main
4+
5+
import "core:fmt"
6+
import "core:intrinsics"
7+
import "core:math"
8+
import "core:strconv"
9+
import "core:os"
10+
11+
PI :: 3.141592653589793;
12+
SOLAR_MASS :: 4 * PI * PI;
13+
DAYS_PER_YEAR :: 365.24;
14+
15+
main :: proc(){
16+
initBodies()
17+
n := strconv.parse_int(os.args[1]) or_else 1000
18+
fmt.printf("%.9f\n", energy())
19+
for _ in 0..<n {
20+
advance(0.01)
21+
}
22+
fmt.printf("%.9f\n", energy())
23+
}
24+
25+
Body:: struct {
26+
x, y, z, vx, vy, vz, mass: f64,
27+
}
28+
SIZE :: 5
29+
bodies: #soa[SIZE]Body
30+
initBodies::proc(){
31+
bodies[0]=sun()
32+
bodies[1]=jupiter()
33+
bodies[2]=saturn()
34+
bodies[3]=uranus()
35+
bodies[4]=neptune()
36+
px, py, pz:f64
37+
for value in bodies {
38+
px += value.vx * value.mass;
39+
py += value.vy * value.mass;
40+
pz += value.vz * value.mass;
41+
}
42+
sun := bodies[0]
43+
offsetMomentum(&sun,px,py,pz)
44+
bodies[0]=sun
45+
}
46+
advance::proc(dt:f64){
47+
N :: (SIZE-1)*SIZE/2
48+
dx,dy,dz,dts :#simd[2]f64
49+
dts = {dt,dt}
50+
Vector3 ::struct{dx,dy,dz:f64}
51+
rt:#soa[N]Vector3
52+
mag:[N]f64
53+
k:int
54+
for i in 0..<SIZE-1 {
55+
ibody := &bodies[i]
56+
for j in i+1..<SIZE {
57+
rt[k].dx = ibody.x - bodies[j].x
58+
rt[k].dy = ibody.y - bodies[j].y
59+
rt[k].dz = ibody.z - bodies[j].z
60+
k += 1
61+
}
62+
}
63+
for i:=0;i<N;i+=2{
64+
dx = intrinsics.unaligned_load(cast(^#simd[2]f64)&rt.dx[i])
65+
dy = intrinsics.unaligned_load(cast(^#simd[2]f64)&rt.dy[i])
66+
dz = intrinsics.unaligned_load(cast(^#simd[2]f64)&rt.dz[i])
67+
dsquared := dx*dx+dy*dy+dz*dz
68+
distance := intrinsics.sqrt(dsquared)
69+
dmag := dts/(dsquared*distance)
70+
intrinsics.unaligned_store(cast(^#simd[2]f64)&mag[i],dmag)
71+
}
72+
k = 0
73+
for i in 0..<SIZE-1 {
74+
ibody := &bodies[i]
75+
for j in i+1..<SIZE {
76+
ibody.vx -= rt[k].dx * bodies[j].mass * mag[k]
77+
ibody.vy -= rt[k].dy * bodies[j].mass * mag[k]
78+
ibody.vz -= rt[k].dz * bodies[j].mass * mag[k]
79+
80+
bodies[j].vx += rt[k].dx * ibody.mass * mag[k]
81+
bodies[j].vy += rt[k].dy * ibody.mass * mag[k]
82+
bodies[j].vz += rt[k].dz * ibody.mass * mag[k]
83+
k += 1
84+
}
85+
}
86+
for i in 0..<SIZE {
87+
bodies[i].x += dt * bodies[i].vx
88+
bodies[i].y += dt * bodies[i].vy
89+
bodies[i].z += dt * bodies[i].vz
90+
}
91+
}
92+
energy::proc()->f64{
93+
e :f64
94+
for i in 0..<SIZE {
95+
ibody := bodies[i]
96+
dx,dy,dz,distance:f64
97+
e += 0.5 * ibody.mass * (ibody.vx*ibody.vx+ibody.vy*ibody.vy+ibody.vz*ibody.vz)
98+
for j in i+1..<SIZE {
99+
jbody := bodies[j]
100+
dx = ibody.x - jbody.x
101+
dy = ibody.y - jbody.y
102+
dz = ibody.z - jbody.z
103+
distance = math.sqrt(dx*dx+dy*dy+dz*dz)
104+
e -= (ibody.mass * jbody.mass) / distance
105+
}
106+
}
107+
return e
108+
}
109+
110+
jupiter :: proc ()-> Body {
111+
return Body {
112+
x = 4.84143144246472090e+00,
113+
y = -1.16032004402742839e+00,
114+
z = -1.03622044471123109e-01,
115+
vx = 1.66007664274403694e-03 * DAYS_PER_YEAR,
116+
vy = 7.69901118419740425e-03 * DAYS_PER_YEAR,
117+
vz = -6.90460016972063023e-05 * DAYS_PER_YEAR,
118+
mass = 9.54791938424326609e-04 * SOLAR_MASS,
119+
}
120+
}
121+
saturn :: proc()-> Body {
122+
return Body{
123+
x = 8.34336671824457987e+00,
124+
y = 4.12479856412430479e+00,
125+
z = -4.03523417114321381e-01,
126+
vx = -2.76742510726862411e-03 * DAYS_PER_YEAR,
127+
vy = 4.99852801234917238e-03 * DAYS_PER_YEAR,
128+
vz = 2.30417297573763929e-05 * DAYS_PER_YEAR,
129+
mass = 2.85885980666130812e-04 * SOLAR_MASS,
130+
}
131+
}
132+
uranus :: proc()->Body {
133+
return Body{
134+
x = 1.28943695621391310e+01,
135+
y = -1.51111514016986312e+01,
136+
z = -2.23307578892655734e-01,
137+
vx = 2.96460137564761618e-03 * DAYS_PER_YEAR,
138+
vy = 2.37847173959480950e-03 * DAYS_PER_YEAR,
139+
vz = -2.96589568540237556e-05 * DAYS_PER_YEAR,
140+
mass = 4.36624404335156298e-05 * SOLAR_MASS,
141+
}
142+
}
143+
neptune :: proc()->Body{
144+
return Body{
145+
x = 1.53796971148509165e+01,
146+
y = -2.59193146099879641e+01,
147+
z = 1.79258772950371181e-01,
148+
vx = 2.68067772490389322e-03 * DAYS_PER_YEAR,
149+
vy = 1.62824170038242295e-03 * DAYS_PER_YEAR,
150+
vz = -9.51592254519715870e-05 * DAYS_PER_YEAR,
151+
mass = 5.15138902046611451e-05 * SOLAR_MASS,
152+
}
153+
}
154+
sun :: proc()->Body{
155+
return Body{
156+
mass = SOLAR_MASS,
157+
}
158+
}
159+
offsetMomentum::proc(self:^Body, px, py, pz:f64){
160+
self.vx = -px / SOLAR_MASS;
161+
self.vy = -py / SOLAR_MASS;
162+
self.vz = -pz / SOLAR_MASS;
163+
}

bench/bench_odin.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ problems:
1616
- name: nbody
1717
source:
1818
- 1.odin
19+
- 1-i.odin
1920
- name: mandelbrot
2021
source:
2122
- 1.odin

0 commit comments

Comments
 (0)