这个问题的目标是能够获得第 2.000.000 个素数,并能够分辨出第 2.000.000 个素数是哪个。
我们从这段代码开始:
#include <stdlib.h>
#include <stdio.h>
#define N 2000000
int p[N];
main(int na,char* arg[])
{
int i;
int pp,num;
printf("Number of primes to find: %d\n",N);
p[0] = 2;
p[1] = 3;
pp = 2;
num = 5;
while (pp < N)
{
for (i=1; p[i]*p[i] <= num ;i++)
if (num % p[i] == 0) break;
if (p[i]*p[i] > num) p[pp++]=num;
num += 2;
}
printf("The %d prime is: %d\n",N,p[N-1]);
exit(0);
}
现在我们被要求通过 pragma omp 使这个进程线程化。这是我到目前为止所做的:
#include <stdlib.h>
#include <stdio.h>
#define N 2000000
#define D 1415
int p[N];
main(int na,char* arg[])
{
int i,j;
int pp,num;
printf("Number of primes to find: %d\n",N);
p[0] = 2;
p[1] = 3;
pp = 2;
num = 5;
while (pp < D)
{
for (i=1; p[i]*p[i] <= num ;i++)
if (num % p[i] == 0) break;
if (p[i]*p[i] > num) p[pp++]=num;
num += 2;
}
int success = 0;
int t_num;
int temp_num = num;
int total = pp;
#pragma omp parallel num_threads(4) private(j, t_num, num, success)
{
t_num = omp_get_thread_num();
num = temp_num + t_num*2;
#pragma omp for ordered schedule(static,4)
for(pp=D; pp<N; pp++) {
success = 0;
while(success==0) {
for (i=1; p[i]*p[i] <= num;i++) {
if (num % p[i] == 0) break;
}
if (p[i]*p[i] > num) {
p[pp] = num;
success=1;
}
num+=8;
}
}
}
//sort(p, 0, N);
printf("El %d primer es: %d\n",N,p[N-1]);
exit(0);
}
现在让我解释我的“部分”解决方案,因此,我的问题。
第一个 D 素数是用序列码获得的,所以现在我可以检查大量数字的可分性。
每个线程都运行一个素数对角线,因此线程之间没有依赖关系,也不需要同步。但是,这种方法的问题如下:
- 一个线程可能比另一个线程产生更多的素数
- 作为问题 1. 的直接结果,它将生成 N 个素数,但它们不会被排序,所以当素数计数器 'pp' 达到 'N' 时,最后一个素数不是第 2.000.000 个素数,它是更高级的主要。
- 也可能是当它生成 2.000.000 个素数时,可以到达真正的第 2.000.000 个素数的线程可能没有足够的时间将其放在素数数组“p”上。
问题/困境是:
我怎么能知道第 2.000.000 个素数何时生成?
提示:有人告诉我,我应该分批(比方说)10.000 个素数候选。然后当我不知道的事情发生时,我会知道最后一批 10.000 个候选人包含第 2.000.000 个素数,我可以使用快速排序对其进行排序。
我希望我说清楚了,这真的很艰难,我只是不停地尝试了几天。