我正在尝试打印2**32以下的所有素数。现在我正在使用bool vector构建一个筛子,然后打印出筛子后的素数。仅打印出10亿个素数就需要4分钟。有没有更快的方法来做到这一点??这是我的代码
#include <iostream>
#include <cstdlib>
#include <vector>
#include <math.h>
using namespace std;
int main(int argc, char **argv){
long long limit = atoll(argv[1]);
//cin >> limit;
long long sqrtlimit = sqrt(limit);
vector<bool> sieve(limit+1, false);
for(long long n = 4; n <= limit; n += 2)
sieve[n] = true;
for(long long n=3; n <= sqrtlimit; n = n+2){
if(!sieve[n]){
for(long long m = n*n; m<=limit; m=m+(2*n))
sieve[m] = true;
}
}
long long last;
for(long long i=limit; i >= 0; i--){
if(sieve[i] == false){
last = i;
break;
}
}
cout << last << endl;
for(long long i=2;i<=limit;i++)
{
if(!sieve[i])
if(i != last)
cout<<i<<",";
else
cout<<i;
}
cout<<endl;
字符串
7条答案
按热度按时间cuxqih211#
我讨论了在我的blog上生成大量素数的问题,我发现第一个十亿个素数的总和是11138479445180240497。我描述了四种不同的方法:
1.蛮力,从2开始试除法。
1.使用2,3,5,7轮生成候选项,然后使用以2、7和61为底的强伪素数测试来测试素数性;这种方法只适用于2^32,这不足以让我对前10亿个素数求和,但对你来说已经足够了。
1.埃拉托色尼的一种分段筛,速度非常快,但需要空间来存储筛分素数和筛本身。
disho6za2#
我已经在C++20中实现了erastosthenes的筛选,并使用多线程完成了非素数的穿孔:
字符串
几乎所有的CPU时间都花在了多线程代码中,用于对非质数进行打孔。在打孔线程中,位范围被分区以适应L2缓存。如果线程数量超过SMT系统上逻辑核数量的一半,则线程子分区的大小为一半。
我只是增加了只存储奇素数的功能,即不存储2的倍数,从而提高了大约87%的性能。
在我的Ryzen 9 7950 X Zen 4 16核CPU上,产生所有素数高达2^32,这几乎是210 E6素数,在所有核心上大约需要0.15秒,抑制文件输出;在一个核心上,算法大约需要1.73秒。程序的第三个参数是线程数。在我的16个核心Zen 4上有16个线程,在一个线程上,我得到了70%的扩展。占用更多的SMT兄弟线程几乎不会带来进一步的加速,因为代码依赖于L2缓存的吞吐量。
文件输出是通过to_chars和我自己的缓冲来完成的,以加快I/O。在我的计算机(64 GB,PCIe 4.0 SSD)上,从上述范围生成2.2GB的文件大约需要额外的两秒钟。
deyfvvtc3#
这可能会加快一点:
字符串
它有点像埃拉托塞尼筛的逆(不是从极限以下的每个数字开始并消除倍数,而是从2开始并忽略极限以下的倍数)。
gtlvzcf84#
最快的方法可能是使用预先生成的列表。
http://www.bigprimes.net/有前14亿个质数可供下载,其中应该包括300亿以下的所有质数。
我想加载二进制文件可能需要太长的时间,当它是几个千兆字节的大小。
fv2wmkja5#
你有没有衡量过什么是最耗时的?是筛子本身,还是输出的写作?
一个快速的方法来加速筛子是停止担心所有的偶数。只有一个偶数是素数,你可以硬编码它。这将把你的数组大小减少一半,这将极大地帮助你克服物理内存的限制。
字符串
至于输出本身,
cout
是出了名的低效。自己调用itoa
或其他等效函数,然后使用cout.write
输出可能会更高效。您甚至可以采用传统方法,将fwrite
与stdout
一起使用。w8rqjzmb6#
我用C写了一个快速的方法,在我的Ryzen 9 3900x上使用一个线程在三分钟内输出高达40亿个素数。如果你把它输出到一个文件,它最终是2.298GB,我认为它使用了大约20GB的内存来完成。
字符串
uplii1fm7#
我写了代码i python输出所有素数小于10亿在8.7秒.但我不确定如果你的第一个40亿素数或艾伦素数小于.无论如何,这是我的解决方案:
字符串