Skip to content
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

Hw04 frsama #33

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open

Hw04 frsama #33

wants to merge 2 commits into from

Conversation

frsama
Copy link

@frsama frsama commented Jul 29, 2022

源码运行结果

image

优化后运行结果

image

优化细节

1.首先立即尝试就尝试将AOS修改为SOA

使用array替换了vector,效果群拔,立即就将1300ms左右的耗时降低到了130ms出头

2.对初始化下手了

我看汇编代码,发现轮流px[i] py[i] pz[i] vx[i] vy[i] vz[i] mass[i]的方法并没有发生矢量化优化,
结果特地去写了先全部赋值px,在全部赋值px,再全部赋值py的方法。为了处理mass和其它不同情况,还特地写了模板。

结果发现成功的实现了矢量化,而且还发现模板函数以内联的方式插进去了,并没有想象中的jump或者是call。
优化是真的优化了,但是没用也是真的一点用也没有。
初始化时间复杂度O(n),完全比不上step和calc的O(n^2)时间复杂度。

3.尝试抠各种细节

(1)把内层循环中,乘除法为常量的部分拉到外层循环,只需要一次计算即可。
(2)把循环拆开,主要是指计算energy那里,energy自增和自减两部分完全不相关啊,我就拆成了两个循环。因为循环越简单,编译器越容易优化。

但是扣这些细节似乎没什么效果,好像之前光把AOS改为SOA就已经成功矢量化优化了。
我还到处添加了#pragma unroll,压根没用,去网上搜,结果人家说开-O1 -O2 -O3,这个宏就会失效,好像是因为开了优化本身就会尝试unroll。

综上,结果我一顿操作猛如虎,除了改SOA以外,其它操作耗时压根没降多少,就从原来的130ms出头,挤进130ms以内而已,甚至可以说只是误差.......

1.首先立即尝试就尝试将AOS修改为SOA
使用array替换了vector,效果群拔,立即就将1300ms左右的耗时降低到了130ms左右

2.尝试抠各种细节
(1)把内层循环中,乘除法为常量的部分拉到外层循环,只需要一次计算即可。
(2)把循环拆开,主要是指计算energy那里,energy自增和自减两部分完全不相关啊,我就拆成了两个循环。因为循环越简单,编译器越容易优化。
但是扣这些细节似乎没什么效果,好像之前光把AOS改为SOA就已经成功矢量化优化了。
我还到处添加了#pragma unroll,压根没用,去网上搜,结果人家说开-O1 -O2 -O3,这个宏就会失效,好像是因为开了优化本身就会尝试unroll。

3对初始化下手了
我看汇编代码,发现轮流px[i] py[i] pz[i] vx[i] vy[i] vz[i] mass[i]的方法并没有发生矢量化优化,
结果特地去写了先全部赋值px,在全部赋值px,再全部赋值py的方法。为了处理mass和其它不同情况,还特地写了模板。

结果发现成功的实现了矢量化,而且还发现模板函数以内联的方式插进去了,并没有想象中的jump或者是call。
优化是真的优化了,但是没用也是真的一点用也没有。
初始化时间复杂度O(n),完全比不上step和calc的O(n^2)时间复杂度。

结果我一顿操作猛如虎,耗时压根没变多少,就从原来的130ms出头,挤进130ms以内而已,甚至可以说只是误差.......
添加了-ffast-math -march=native优化选项
@frsama
Copy link
Author

frsama commented Jul 29, 2022

那个模板函数内联我觉得挺有意思的。
补充一张图
image
可以看到编译器把模板函数内联了7次,对应.L5~.L11
我以为直接jmp可能会好一些,它这样不知道算不算强行以空间换时间啊。

还有可以看见调用sub_init(),都call了四次rand,这算是直接正面矢量化成功了吧。

就是感觉去优化O(n)部分没什么效果,感觉挺可惜的。
果然还是得抓主要矛盾,但是后面step和calc我暂时想不出更好的方法了。

@blusque
Copy link

blusque commented Aug 26, 2022

我也用你的代码实验了一下,得到的结果是优化了10倍的速度,但过程好像不一样。我这边的情况是,仅仅将vector修改为array或c数组后,编译器并没有成功矢量化。step()函数的汇编如图1所示,
图1
可以看到基本没有成功矢量化,运行时间也与未修改时相差无几。
这时需要做三点修改才能提速,
一是把sqrt更换为std::sqrt或sqrtf,避免掉隐士类型转换;
二是在编译选项中开启-ffast-math
三是把对stars.vx/vy/vz的赋值提出内层循环。
尤其是第三点,可以将前两点提速后的550ms缩减为100ms左右。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants