【问题标题】:Multithreaded prime number generator多线程素数生成器
【发布时间】:2013-04-01 07:21:07
【问题描述】:

我有:

input1: n to generate primes up to
input2: no of threads to generate primes

我实现了这个并且它可以工作,但是问题是,每个线程都会生成自己的素数列表[2, n]

但我希望两个线程都在生成素数的同一任务上工作,彼此切换,而不是独立地。 n如何划分线程数?

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

void *BusyWork(void *threadid)
{
long tid;
tid = (long)threadid;
printf("Hello World! It's me, thread # %ld\n", tid);

double s,d;
int n,i,c,k,p,cs,nsqrt;     
printf( "Input an integer n > 1 to generate primes upto this n:   " ); // prompt 
scanf("%d",&n); 
printf( "Entered integer: %d\n",n);
int array[n];
for(i=0;i<n;i++)
    array[i]=0;
s=sqrt(n);
d=floor(s);
nsqrt = (int) d;

for ( c= 2; c <= nsqrt; c++ )// note here < is not working <= is working here.
    {
        if(array[c]==0)
            {
                cs = c*c;
                k=0;
                for(p=cs; p<n; p=(cs+k*c))
                    {
                        k++;
                        array[p] = 1;
                }//for
            }//if
    }//for

    for ( i = 2; i < n; i++ )
    { 
        if (array[i]==0)
        {
            printf("%5d",i);
        }//if
    }// for
    printf("\n");


    printf("Above prime numbers are generated from me i.e. thread # %ld GOOD BYE!!! \n ", tid);


    pthread_exit((void*) threadid);
    }

  int main (int argc, char *argv[])
  {

   //////// time cal ///////////////////

     struct timespec start, finish;
     double elapsed;

      clock_gettime(CLOCK_MONOTONIC, &start);
     /////////////////////////////////////

    int NUM_THREADS;
     printf("Please Input Total Number of Threads you want to make:-  ");
     scanf("%d",&NUM_THREADS);


     pthread_t thread[NUM_THREADS];
     pthread_attr_t attr;
       int rc;
     long t;
     void *status;

       /* Initialize and set thread detached attribute */
     pthread_attr_init(&attr);
       pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);

      for(t=0; t<NUM_THREADS; t++) {
        printf("Main: creating thread %ld\n", t);
        rc = pthread_create(&thread[t], &attr, BusyWork, (void *)t); 
        if (rc) {
           printf("ERROR; return code from pthread_create() is %d\n", rc);
           exit(-1);
          }
        }

      /* Free attribute and wait for the other threads */
       pthread_attr_destroy(&attr);
      for(t=0; t<NUM_THREADS; t++) {
       rc = pthread_join(thread[t], &status);
      if (rc) {
       printf("ERROR; return code from pthread_join() is %d\n", rc);
       exit(-1);
       }
       printf("Main: completed join with thread %ld having a status of %ld\n",t,  (long)status);
      }

  printf("Main: program completed. Exiting.\n");
   ////////////// time end ////////////////////////
    clock_gettime(CLOCK_MONOTONIC, &finish);

   elapsed = (finish.tv_sec - start.tv_sec);
      elapsed += (finish.tv_nsec - start.tv_nsec) / 1000000000.0;
   printf("Total time spent by the main:  %e \n", elapsed);
    //////////////////////////////////////////////////////////
   pthread_exit(NULL);
     }

【问题讨论】:

  • 您将需要在线程之间分派工作包(主要候选人)或主要候选人范围。在候选者足够大或素数测试更复杂之前,您不太可能看到太多好处。
  • 我不想要素数的帮助。一代部分。我想有一个提示:我想同时生成素数列表,因为如果某个线程生成了一些素数,那么这些素数不是从其他线程生成的。
  • @mAge:所以将数字列表分成两半。

标签: c multithreading pthreads posix primes


【解决方案1】:

您想要的远非微不足道。但这里有一个针对两个线程进行思考、研究和测试的想法。

为此,您需要在两个线程之间“拆分”作业。例如,让第一个线程在[ 2, k ] 之间查找素数,让第二个线程在[ k+1, x ] 之间查找素数。

这是微不足道的部分。问题来了——如何找到x? (k 很简单 - x / 2)。

您应该研究 - 例如,如何找到给定区间内的素数数量。 This 可能有用:它说,你可以使用:

N ~~ x / ln(x)

其中N 是质数的个数,小于 x。

好吧,我不是数学家,我现在不能给你解决方案,但应该有办法让N找到x

请注意,这适用于大量数字。

因此,有了这个,一旦你找到 x,你就可以在两个线程之间拆分工作。

如您所见,这确实远非微不足道,并且没有精确(精确)的方法可以找到 x (N)。


当然,另一种微不足道的方法(更简单但不是那么好)是知道N 的范围并将其分成两个区间。或者,找到第一个,比如说,100 个素数并不是什么大问题。但是找到前 1000 个是另一回事。在这种情况下,例如,您可以为每个 +500 素数启动额外的线程。


另一个想法是进行研究以找到N-th 素数的近似值。这可能会有所帮助:Is there a way to find the approximate value of the nth prime?

【讨论】:

  • 谢谢!这很好,但是是否有任何服务/例程可以在线程之间分块共享作业。
  • 有一个名为 openMP (en.wikipedia.org/wiki/OpenMP) 的库,它可能会有所帮助,但我不确定。对于线程来说,这不是一项微不足道的“工作”,我怀疑 openMP 会有所帮助。但我从未使用过它,因此您可以对此进行一些研究,看看是否有帮助。
【解决方案2】:

抱歉,如果我误解了您的帖子,但我怀疑您误解了多线程的含义。您的代码和最后一个问题表明您认为启动多个相同的线程意味着它们会以某种方式自动在它们之间划分任务。这从根本上是不正确的。我们都希望是这样,但事实并非如此。

有几种方法。有一种“手动”方法,您可以利用问题中的并行性机会并为每个位编写一个线程(或使用不同的参数多次启动同一个线程。无论哪种方式线程+数据都不相同)。然后,您可以并行运行这些线程。本质上,这就是 Kirol Kirov 建议的方法。

另一种可以很好地解决长循环数学问题的替代方法是使用编译器,该编译器可以在运行时自动将循环分解为单独的线程。这意味着您编写普通的单线程代码并告诉编译器在可以确定这样做安全的地方生成线程。为您节省大量工作,并在适当的情况下产生有效的结果。 Sun C 编译器可以在 Solaris 上执行此操作,而 Intel 编译器也可以执行此操作(可能仅在 Windows 上)。对最新和最伟大的研究进行一些研究可能是值得的。但是,这不会教您任何有关多线程编程的知识。

另一种方法是使用 openMPI 之类的东西(我认为)它允许您在 for 循环之前放置 #pragma 语句,以表示您希望并行执行 tile 循环。有点像 Intel 和 Sun 编译器的手动版本。

【讨论】:

  • 我理解您的建议/指出,但无需道歉!实际上我想这样做,并且我希望它以更好的方式但在 POSIX 中。就像 cmets 那样做。我认为java的运行+执行服务,会自动执行吗?但我会确认这一点......
  • 感谢您在您的帖子中推荐我。只是一件小事-我认为您的意思是 OpenMP,而不是 OpenMPI(MPI 是另一个库):)
猜你喜欢
  • 2021-08-30
  • 1970-01-01
  • 2020-06-27
  • 1970-01-01
  • 2023-04-04
  • 1970-01-01
  • 2015-06-23
  • 1970-01-01
相关资源
最近更新 更多