有没有办法让这个程序更快?

时间:2021-05-15 11:56:37

标签: c

有没有办法让这个程序在 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);
}

1 个答案:

答案 0 :(得分:1)

我想到了两种算法:

Eratosthenes 和 OpenMP。

我的意思不是“纯粹的”筛分实施。但是较小素数有助于找到较大素数的基本思想。无需除以每个奇数。

这是您尝试使用 i+=6 技巧的方法。这仅适用于较低的地区。通过一组找到的素数,可能的除数被集中。是将它们用作筛子还是用于试除是次要的(分段筛子比除法更快)。

当然,对于随机素数候选者,这不太明显。但是对于多达 20 亿(RAND_MAX)的大量候选,多达 44000 个素数的数组就足够了。与 3.8 秒相比,很快就完成了。

(也有数学算法,也使用某种表格 - 看看有多快,例如 factor 实用程序)

关于并发问题:

所有这些线程包括。计数可以由一个(半)OpenMP 行处理。不仅更容易,而且更快,甚至可能在您解决瓶颈之后也是如此。

所以这将是一个用于并行编程的现成算法。


很棒的 XY 笑话:您要求快速的素数算法,但问题是线程中断。