我有一个类似于以下代码的代码,用于在一个范围内查找素数(使用Eratosthenes筛选)并使用OpenMP进行并行化。在此之前,我有一个预处理阶段,我将所有的偶数和3和5的倍数标记出来,这样我就不必在这个阶段做更少的工作。 测试床共享三级缓存为12MB,物理内存为32 GB。我正在使用12个线程。 flag
阵列是unsigned char
。并行化大循环并改进高速缓存访问
#pragma omp parallel for
for (i = 0; i < range; i++)
{
for (j = 5; j < range; j+=2)
{
if(flag[i] == 1 && i*j < range)
if (flag[i*j] == 1)
flag[i*j] = 0;
}
}
这个程序适用于小于1,000,000的范围......但是在此之后,执行时间会在更大范围内出现;例如range = 10,000,000
这个程序需要大约70分钟(不适合缓存?)。我已经修改了上面的程序来合并循环平铺,以便它可以将缓存用于任何循环范围,但即使阻塞方法似乎也很耗时。交换循环也不利于大范围。
如何修改上面的代码来处理大范围?我怎么能重写代码,使其完全平行(range
和flag
[因为flag
数组非常大,所以我不能声明它是私人]共享)?
是的,我遵循了你的建议重新编写我的代码,性能仍然不如你的,但它对于单线程(单线程为50s,对于12线程为5)显着下降。我确信我可以更多地调整我的代码,并且在对结果感到满意时包括在编辑中。 – Sayan
你实施了哪些优化?我只是看着我自己的实现。它是单线程的,并不预先计算sqrt(N)表。但它使用了一个“压缩”位域,其中每个位代表一个奇数。 (所以它比char-array的内存效率高出16倍)。对于2^31,我在Core i7 720QM上获得了16秒的时间。 (http://www.xtremesystems.org/forums/showthread.php?221773-New-Multi-Threaded-Pi-Program-Faster-than-SuperPi-and-PiFast&p=4230543&viewfull=1#post4230543) – Mysticial
我预先计算sqrt (N)表(这个过程有循环携带的依赖关系,所以目前不是平行的),并且在第二部分,我只是发现从sqrt(N)到N的素数,正如你所建议的(这是完全平行的,循环)。我不知道如何实现压缩位域,但我会检查网址并做一些Google搜索。谢谢。 – Sayan