Skip to content

Hw04 frsama #33

New issue

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

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

Already on GitHub? # to your account

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以内而已,甚至可以说只是误差.......

frsama added 2 commits July 29, 2022 21:12
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左右。

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

Successfully merging this pull request may close these issues.

2 participants