利用OpenMP实现埃拉托斯特尼(Eratosthenes)素数筛法并行化

1.算法简介

1.1筛法起源

筛法是一种简单检定素数的算法。据说是古希腊的埃拉托斯特尼(Eratosthenes,约公元前274~194年)发明的,又称埃拉托斯特尼筛法(sieve of Eratosthenes)。

1.2筛法过程

具体做法是:给出要筛数值的范围 n,找出 n√以内的素数p1,p2,p3,……,pk。从最小素数2去筛,即把2留下,把2的倍数剔除掉;再用下一个素数,也就是3筛,把3留下,把3的倍数剔除掉;接下去用下一个素数5筛,把5留下,把5的倍数剔除掉;不断重复下去。

2.实现代码

代码为Linux平台,可简单修改移植到Windows。使用OpenMP实现简单的并行加速,有关OpenMP的用法,百度搜索“OpenMP简易教程”。

#include <cmath>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <iostream>
#include <sys/time.h>
#include <cassert>
#include <omp.h>
using namespace std;
typedef unsigned int uint32;
typedef unsigned long long int uint64;

inline void sieve(uint64 start,uint64 end,uint64& num,int threadNum)
{
  assert(start>1);
  bool* a =new bool[end+1];
  memset(a+2,true,end+1);

  #pragma omp parallel for num_threads(threadNum)
  for (uint64 i = 2; i <=(uint64)sqrt(end); i++)
  {
    if (a[i])
      for (uint64 j = i; i*j <= end; j++)
        a[i*j] = false;
  }
  uint64 prime_num=0;
  if(start==2)
    prime_num++;

  #pragma omp parallel for num_threads(threadNum) reduction(+: prime_num)
  for (uint64 i =(start%2==0?start+1:start); i <=end ;i += 2)
  {
    if (a[i])
      prime_num++;
  }
  num=prime_num;
  delete[] a;
} 

int main(int argc,char* argv[])
{
    if(argc!=4){
      fprintf(stderr, "usage: Eratosthenes start_number end_number threadNum\n");
      exit(-1);
    }
    struct timeval ts,te;
    uint64 start=atoi(argv[1]);
    uint64 end=atoi(argv[2]);
    int threadNum=atoi(argv[3]);
    uint64 num=0;
    gettimeofday(&ts,NULL);
    sieve(start,end,num,threadNum);
    gettimeofday(&te,NULL);
    cout<<"count: "<<num<<endl;
    cout<<"total time: "<<((te.tv_sec-ts.tv_sec)*1000+(te.tv_usec-ts.tv_usec)/1000)<<"ms"<<endl;
    getchar();
    return 0;
}

参考文献

[1]百度百科-筛法

时间: 2024-10-11 23:48:24

利用OpenMP实现埃拉托斯特尼(Eratosthenes)素数筛法并行化的相关文章

[java]埃拉托斯特尼筛法检定素数

埃拉托斯特尼筛法,简称埃氏筛或爱氏筛,是一种由希腊数学家埃拉托斯特尼所提出的一种简单检定素数的算法.要得到自然数n以内的全部素数,必须把不大于根号n的所有素数的倍数剔除,剩下的就是素数. 要得到自然数n以内的全部素数,必须把不大于 的所有素数的倍数剔除,剩下的就是素数. 给出要筛数值的范围n,找出以内的素数.先用2去筛,即把2留下,把2的倍数剔除掉:再用下一个质数,也就是3筛,把3留下,把3的倍数剔除掉:接下去用下一个质数5筛,把5留下,把5的倍数剔除掉:不断重复下去....... java源码

数论部分第二节:埃拉托斯特尼筛法

埃拉托斯特尼筛法 质数又称素数.指在一个大于1的自然数中,除了1和此整数自身外,没法被其他自然数整除的数.怎么判断n以内的哪些数是质数呢? 埃拉托斯特尼筛法 厄拉多塞是一位古希腊数学家,他在寻找素数时,采用了一种与众不同的方法:先将2-N的各数放入表中,然后在2的上面画一个圆圈,然后划去2的其他倍数:第一个既未画圈又没有被划去的数是3,将它画圈,再划去3的其他倍数:现在既未画圈又没有被划去的第一个数是5,将它画圈,并划去5的其他倍数……依次类推,一直到所有小于或等于N的各数都画了圈或划去为止.这

生成素数序列----埃拉托斯特尼筛法

下面是埃拉托斯特尼筛法的实现代码: boolean[] sieveOfEratosthenes(int max) { boolean[] flags = new boolean[max + 1]; int count = 0; init(flags);//将flags中0,1元素除外的所有元素设为true int prime = 2; while (prime <= max) { //划掉余下为prime倍数的数字 crossOff(flags, prime); //找出下一个为true的值 p

埃拉托斯特尼素数筛法

1 //埃拉托斯特尼筛法 2  3 int prime[maxx]; 4 bool is_prime[maxx+1];//is_prime[i]为true表示i为素数 5  6 //返回n以内素数的个数 7 int sieve (int n) 8 { 9     int p=0;10     for(int i=0; i<=n; i++) is_prime[i]=1;11     //memset(is_prime,1,sizeof(is_prime));12     is_prime[0]=i

质数筛选方法(埃拉托斯特尼筛法)

今天刷题刷了这么一道题, The sum of the primes below 10 is 2 + 3 + 5 + 7 = 17. Find the sum of all the primes below two million. 大概意思是10以内的质数加法和为 2 + 3 + 5 + 7 = 17,接着求2000000以内质数加法的和. 分析:要求2000000内质数的和,首先得把2000000内的质数表示出来,我用了上篇博客的方法,呵呵,半天没跑出来,这就说明方法不对,上网搜了搜,发现埃

素数个数统计——埃拉托斯特尼筛法

1 算法思想 给出要筛数值的范围n,找出以内的素数.先用2去筛,即把2留下,把2的倍数剔除掉:再用下一个素数,也就是3筛,把3留下,把3的倍数剔除掉:接下去用下一个素数5筛,把5留下,把5的倍数剔除掉:不断重复下去....... 2 Python实现 1 from math import sqrt 2 3 def countPrimes(n): 4 if n in (0, 1, 2): 5 return 0 6 boards = [True] * n 7 boards[0] = boards[1

BitArray编写埃拉托斯特尼筛法(原书错误,学习更正)

刚开始代码无法运行,修改后原书代码可以运行了,可是书本的思想还是错的. 虽然接下来的都是讲错误的思想下的"错误"的修改. 原书缺了窗体控件的代码,虽然在VS下不需要手动写窗体的代码,但是刚开始确实也不会怎么弄窗体 记录窗体拖拽的方法: 首要的一步是新建一个Windows窗体应用程序:文件 --> 新建 --> 项目 --> 选择Windows窗体应用程序: 此时VS界面左侧应当要有"工具箱",有的话这里面的控件就可以直接拖了,没有的话需要设置 在第

埃拉托斯特尼--筛法 c++求质数,用bitset类型

要得到自然数n以内的全部素数,必须把不大于 的所有素数的倍数剔除,剩下的就是素数. 给出要筛数值的范围n,找出以内的素数. 1既不是质数也不是合数,去掉: 先用2去筛,即把2留下,把2的倍数剔除掉: 再用下一个质数,也就是3筛,把3留下,把3的倍数剔除掉: 接下去用下一个质数5筛,把5留下,把5的倍数剔除掉:不断重复下去....... 主要用到bitset类型 1 #include<iostream> 2 #include<string> 3 #include<bitset&

线性筛选(埃拉托斯特尼筛法升级版欧拉筛法)

原理: 任何一个合数都可以表示成一个质数和一个数的乘积 假设A是一个合数,且A = x * y,这里x也是一个合数,那么有: A = x * y; (假设y是质数,x合数) x = a * b; (假设a是质数,且a < x-->>a<y) -> A = a b y = a Z (Z = b y) 即一个合数(x)与一个质数(y)的乘积可以表示成一个更大的合数(Z)与一个更小的质数(a)的乘积,那样我们到每一个数,都处理一次,这样处理的次数是很少的,因此可以在线性时间内得到解