最明显的选择是使用OpenMP。假设您的循环非常容易并行执行多个迭代,那么您可能只需要添加以下代码:
在循环之前添加-fopenmp
,并让它以并行方式执行。根据循环内容的不同,这可能会获得接近线性加速或略微降低代码速度。在后一种情况(减速或最小加速)中,您可以使用OpenMP进行其他操作以帮助加速,但是如果不了解代码本身的基础知识,那么很难猜测要做什么或可望获得的最大改进。
您正在获得的另一个建议("使用线程")可能是适当的。 OpenMP基本上是一种自动化方式,用于针对特定类型的并行代码利用线程。对于诸如您所描述的情况(并行执行多个循环迭代),通常更喜欢使用OpenMP-它要简单得多,并且除非您非常了解多线程和/或为将代码并行化而付出大量努力,否则可能会获得更好的性能。
编辑:
你在问题中提供的代码可能不会从多个线程中受益。问题在于,在将结果写入内存之前,它对每个数据项的计算非常少。即使单个核心可以在足够快的时间内完成计算,整体速度也可能受到与内存的带宽有关的限制。
要有机会从多个线程中获得一些实际利益,您可能需要编写一些执行更多计算和更少读写内存的代码。例如,如果我们将您的计算合并在一起,并在单个项目上执行所有计算,然后汇总结果:
double total = 0;
for (int i = 0; i < size; i++)
total += sin(i) + sin(i*i) + sin(sqrt(i)) + cos(i*i);
通过添加一个编译指示:
如果我们在for
循环之前加入OpenMP,我们有很大的机会看到执行速度的显著提高。没有OpenMP,我得到了如下时间:
Real 16.0399
User 15.9589
Sys 0.0156001
...但是当我编译时启用#pragma
和OpenMP,我会得到这样的时间:
Real 8.96051
User 17.5033
Sys 0.0468003
因此,在我的(双核)处理器上,时间从16秒降至9秒 - 并非快了两倍,但相当接近。当然,您获得的改进很大程度上取决于您可用的核心数量。例如,在我的另一台计算机上(使用Intel i7 CPU),我获得了更大的改进,因为它具有更多的核心。
没有OpenMP:
Real 15.339
User 15.3281
Sys 0.015625
...并使用OpenMP:
Real 3.09105
User 23.7813
Sys 0.171875
为了完整起见,这是我使用的最终代码:
#include <math.h>
#include <iostream>
static const int size = 1024 * 1024 * 128;
int main(){
double total = 0;
#pragma omp parallel for reduction(+:total)
for (int i = 0; i < size; i++)
total += sin(i) + sin(i*i) + sin(sqrt(i)) + cos(i*i);
std::cout << total << "\n";
}