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 #13

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

HW04 #13

wants to merge 2 commits into from

Conversation

Mwsxy
Copy link

@Mwsxy Mwsxy commented Jan 7, 2022

------baseline------
Initial energy: -5.272538
Final energy: -5.227708
Time elapsed: 1720 ms
------   my   ------
original:
Initial energy: -5.272539
Final energy: -5.227711
Time elapsed: 1104 ms
my:
Initial energy: -5.272539
Final energy: -5.265044
Time elapsed: 163 ms
------   my2  ------
original:
Initial energy: -5.272539
Final energy: -5.227711
Time elapsed: 1105 ms
my:
Initial energy: -5.272539
Final energy: -5.227718
Time elapsed: 107 ms

优化结果

尝试了一些优化方法,目前最快只能达到100ms左右。
work2.cpp对应的是my2的结果,对比同等编译选项的原来的源代码快10.33倍,比原工程快16倍。
work.cpp对应的是my的结果,对比同等编译选项快6.77倍,对比原工程优化快10.55倍。

优化思路

编译选项

首先想到的是数学计算,考虑到原算法确保了不会出现计算得到NaN的情况,果断开启-ffast-math -march=native选项。
可以和baseline对比发现速度明显提高不少。

AOS-->SOA

原来的数据包装是比较符合OOP的封装,但是7个float既没有8字节对齐,也不利于编译器自动优化。改为SOA后速度提升。
从godbolt上可以明显看到SIMD的汇编指令变多了。

复制数据去除数据依赖

step函数明显是一个二维循环遍历,编译器自动优化时star和other都是来自同一数组的迭代器,指令流水线容易产生读写冲突。因此可以复制一份原始数据作为other使用,而且other从算法上看也是只发生读取的,复制一份没有问题。解决可能发生的数据读写依赖冲突后,编译器优化性能大幅提升,基本达到work.cpp的性能。

sqrt函数

step中循环的迭代部分,最耗时的操作无疑就是sqrt。因此改用std::sqrt能够避免使用双精度指令浪费性能,而且使编译器优化得更加快,更加好。又或者使用更快的开方计算技巧,我尝试了著名的雷神之锤3中的开方函数,效果还可以,比std::sqrt快一点点,并且这个条件下可以关闭-ffast-math选项。

手写SIMD

尝试了下手写SIMD,直接在外围循环展开。由于机器限制只能使用256位计算。但是速度确实很快,达到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