有没有办法让这个程序在 10000000 个数字上的运行速度超过 3.8 秒?此代码检查随机生成的数字,并对其中的质数进行计数和求和。我使用 4 个线程,每个线程都在一个核心上运行。我很确定有某种算法比这个检查素数更快,但我找不到。
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <math.h>
#include <semaphore.h>
long sum=0,count=0;
pthread_mutex_t lock;
int numOfRandomNumbers;
int isPrime(int num)
{
int i;
if(num==2||num==3)
return 1;
if(num%2==0||num%3==0)
return 0;
if((num-1)%6!=0&&((num+1)%6)!=0||((num*num)-1)%8!=0)return 0;
for (i = 5;i*i<=num;i+=6)
{
if (num%i == 0||num%(i+2)==0)return 0;
}
return 1;
}
void* prime(void * arg)
{
int size=*(int*) arg;
int random;
for(int i=0;i<size;i++)
{
random=rand();
if(isPrime(random))
{
pthread_mutex_lock(&lock);
sum+=random;
count+=1;
pthread_mutex_unlock(&lock);
}
}
}
int main(int argc, char *argv[])
{
if(pthread_mutex_init(&lock,NULL)!=0)
{
printf("mutix init failed\n"); return 0;
}
if(argc != 3)
{
printf("Too few arguments ");
printf("USAGE: ./primeCalc <prime pivot> <num of random numbers>");
exit(0);
}
pthread_t tids[4];
int randomPivot = atoi(argv[1]);
numOfRandomNumbers = atoi(argv[2]);
int random = rand();
srand(randomPivot);
long size1 =numOfRandomNumbers/4;
long size2=(2*numOfRandomNumbers/4)-numOfRandomNumbers/4;
long size3=(3*numOfRandomNumbers/4)-(2*numOfRandomNumbers/4);
long size4=numOfRandomNumbers-(3*numOfRandomNumbers/4);
pthread_create(&tids[0], NULL, prime, &size1);
pthread_create(&tids[1], NULL, prime, &size2);
pthread_create(&tids[2], NULL, prime, &size3);
pthread_create(&tids[3], NULL, prime, &size4);
pthread_join(tids[0], NULL);
pthread_join(tids[1], NULL);
pthread_join(tids[2], NULL);
pthread_join(tids[3], NULL);
pthread_mutex_destroy(&lock);
//keep the out format as this!!
printf("%ld,%ld\n",sum,count);
exit(0);
}
答案 0 :(得分:1)
我想到了两种算法:
Eratosthenes 和 OpenMP。
我的意思不是“纯粹的”筛分实施。但是较小素数有助于找到较大素数的基本思想。无需除以每个奇数。
这是您尝试使用 i+=6
技巧的方法。这仅适用于较低的地区。通过一组找到的素数,可能的除数被集中。是将它们用作筛子还是用于试除是次要的(分段筛子比除法更快)。
当然,对于随机素数候选者,这不太明显。但是对于多达 20 亿(RAND_MAX)的大量候选,多达 44000 个素数的数组就足够了。与 3.8 秒相比,很快就完成了。
(也有数学算法,也使用某种表格 - 看看有多快,例如 factor
实用程序)
关于并发问题:
所有这些线程包括。计数可以由一个(半)OpenMP 行处理。不仅更容易,而且更快,甚至可能在您解决瓶颈之后也是如此。
所以这将是一个用于并行编程的现成算法。
很棒的 XY 笑话:您要求快速的素数算法,但问题是线程中断。