C/Linux下多线程Eratosthenes的筛选

mccptt67  于 2022-12-11  发布在  Linux
关注(0)|答案(4)|浏览(210)

我目前正在使用C多线程计算埃拉托色尼筛。
我们的目标是首先创建一个主线程,它使用一个split函数将对数字的探索划分到多个线程上。

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

void *creat_thread(int *nbThreads);

void *SieveEratosthenes(int *tailleTab);

int* tab;
int sizeTab;
int nbTachesParThread=0;

int main(void)
{
  int nbThreads;
  int n;
  do{
    printf("Enter an integer > 1 :  ");
    scanf("%d", &n);
  } while(n<2);

  sizeTab = n+1;
  tab = (int*)malloc(tailleTab*sizeof(int));
  for (unsigned int i=0; i<tailleTab; i++)
  {
    tab[i] = 1;
  }

  do{
    printf("Enter a number positive number of threads : ");
    scanf("%d", &nbThreads);
  } while(nbThreads<1);

  pthread_t threadPrincipal;

  if (pthread_create(&threadPrincipal, NULL, creat_thread, NULL)) {
    perror("pthread_create");
    return EXIT_FAILURE;
  }

  if (pthread_join(threadPrincipal, NULL)) {
    perror("pthread_join");
    return EXIT_FAILURE;
  }

  printf("The Prime numbers are : \n");
  for(unsigned int i=0; i<sizeTab; i++)
  {
    if(tab[i]==1)
    {
      printf("%d\n", (i));
    }
  }

}

void *creat_thread(int *nbThreads)
{

  int nbTachesParThread = (int) sqrt(sizeTab) / nbThreads;
  pthread_t* threads = (pthread_t*)malloc(nbThreads*sizeof(pthread_t));

  int plageThreadi = nbTachesParThread;

  for(int i = 0; i < nbThreads; ++i)
    pthread_create (&threads[i], NULL, SieveEratosthenes, plageThreadi);
    plageThreadi += nbTachesParThread;
}

void *SieveEratosthenes(int *plageThread)
{

  for( int i=(plageThread - nbTachesParThread); i<=plageThread; i++)
  {
    if (tab[i] == 1)
    {
      for (int j = i*i; j<sizeTab; j += i)
      {
        tab[j]=0;
      }
    }
  }

}

我尝试实现一个代码,但在运行时出现错误:

segmentation error (core dumped)
cxfofazt

cxfofazt1#

除了我在这里的评论中提到的问题之外,还有更多的问题需要解决:
首先,PThread函数需要是void *(*)(void*)类型。代码使用的是void *(*)(int*)类型。不好。
第二,代码没有加入工作线程,因此分发线程在创建完所有工作线程后结束,然后它加入main(),然后访问工作线程最有可能仍在工作的变量,导致未定义的行为,然后结束,结束进程。结束进程取消所有工作线程。

iezvtpos

iezvtpos2#

我遵循了您的建议,创建了一个结构来包含将由所有线程使用的变量。
然而,我注意到,有时它的工作(它显示素数很好),但有时它不工作,它显示要么只有0或所有的数字从0到i。

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

void *creat_thread(void* arg);

void *SieveEratosthenes(void* arg);

struct param
{
  int* tab;
  int sizeTab;
  int nbTachesParThread;
  int nbThreads;
  int plageThreadi;
  int plageThreadPrecedent;
};

int main(void)
{
  struct param p;

  int n;
  do{
    printf("Enter an integer > 1 :  ");
    scanf("%d", &n);
  } while(n<2);

  p.sizeTab = n+1;

  p.tab = (int*)malloc(p.sizeTab*sizeof(int));
  for (unsigned int i=0; i<p.sizeTab; i++)
  {
    p.tab[i] = 1;
  }

  do{
    printf("Enter a number positive number of threads : ");
    scanf("%d", &p.nbThreads);
  } while(p.nbThreads<1);

  pthread_t threadPrincipal;

  if (pthread_create(&threadPrincipal, NULL, (void*)creat_thread, &p)) {
    perror("pthread_create");
    return EXIT_FAILURE;
  }
  if (pthread_join(threadPrincipal, NULL)) {
    perror("pthread_join");
    return EXIT_FAILURE;
  }

  printf("The Prime numbers are : \n");
  for(unsigned int i=0; i<p.sizeTab; i++)
  {
    if(p.tab[i]==1)
    {
      printf("%d\n", i);
    }
  }
}

void *creat_thread(void* arg)
{
  struct param *args = (void*)arg;
  args->nbTachesParThread = (int) sqrt(args->sizeTab) / args->nbThreads;
  pthread_t* threads = (pthread_t*)malloc(args->nbThreads*sizeof(pthread_t));

  args->plageThreadi = args->nbTachesParThread;

  for(int i = 0; i < args->nbThreads; ++i)
    {
      pthread_create (&threads[i], NULL, (void*)SieveEratosthenes, &(*args));
      args->plageThreadPrecedent = args->plageThreadi;
      args->plageThreadi += args->nbTachesParThread;
    }

  for(int i = 0; i < args->nbThreads; ++i)
      {
        pthread_join(threads[i], NULL);
      }
  pthread_exit(NULL);
}

void *SieveEratosthenes(void* arg)
{
  struct param *args = (void *)arg;
  for(int i=(args->plageThreadPrecedent); i<=args->plageThreadi; i++)
  {
    if (args->tab[i] == 1)
    {
      for (int j = i*i; j<args->sizeTab; j += i)
      {
        args->tab[j]=0;
      }
    }

  }
  pthread_exit(NULL);
}
dohp0rv5

dohp0rv53#

在main()函数中,将对pthread_create()和pthread_join()的调用移到if语句之外。无论pthread_create()调用是否成功,都应该执行这些调用。
在筛中埃拉托斯特尼()函数,则将合数标记为0的循环应该从i * i开始,而不是从i开始。这是因为任何合数都可以写成两个素数的乘积,并且其中一个素数必须小于或等于合数的平方根。因此,如果一个数i是合数,它必须具有小于或等于i的平方根的素因子。
在creat_thread()函数中,将对pthread_join()的调用移到创建线程的循环中,这样可以确保每个线程在创建下一个线程之前都已经完成。
在creat_thread()函数中,将plageThreadPrecedent变量初始化为2,因为这是第一个质数。

egdjgwm8

egdjgwm84#

我已经修改了代码,所以实际上我没有更多的错误代码,但一旦我输入了2个变量(要计算的数量+线程数量),程序运行,但没有显示任何内容。

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

void *creat_thread();

void *SieveEratosthenes();

int* tab;
int sizeTab = 0;
int nbTachesParThread=0;
int nbThreads = 0;
int plageThreadi = 0;
int plageThreadPrecedent = 0;

int main(void)
{
  int n;
  do{
    printf("Enter an integer > 1 :  ");
    scanf("%d", &n);
  } while(n<2);

  sizeTab = n+1;
  tab = (int*)malloc(sizeTab*sizeof(int));
  for (unsigned int i=0; i<sizeTab; i++)
  {
    tab[i] = 1;
  }

  do{
    printf("Enter a number positive number of threads : ");
    scanf("%d", &nbThreads);
  } while(nbThreads<1);

  pthread_t threadPrincipal;

  if (pthread_create(&threadPrincipal, NULL, creat_thread, NULL)) {
    perror("pthread_create");
    return EXIT_FAILURE;
  }

  if (pthread_join(threadPrincipal, NULL)) {
    perror("pthread_join");
    return EXIT_FAILURE;
  }

  printf("The Prime numbers are : \n");
  for(unsigned int i=0; i<sizeTab; i++)
  {
    if(tab[i]==1)
    {
      printf("%d\n", (i));
    }
  }
}

void *creat_thread()
{

  int nbTachesParThread = (int) sqrt(sizeTab) / nbThreads;
  pthread_t* threads = (pthread_t*)malloc(nbThreads*sizeof(pthread_t));

  int plageThreadi = nbTachesParThread;

  for(int i = 0; i < nbThreads; ++i)
    {
      pthread_create (&threads[i], NULL, SieveEratosthenes, NULL);
      pthread_join(threads[i], NULL);
      plageThreadPrecedent = plageThreadi;
      plageThreadi += nbTachesParThread;
    }

  for(int i = 0; i < nbThreads; ++i)
      {
        pthread_join(threads[i], NULL);
      }
  pthread_exit(NULL);
}

void *SieveEratosthenes()
{
  for(int i=(plageThreadPrecedent); i<=plageThreadi; i++)
  {
    if (tab[i] == 1)
    {
      for (int j = i*i; j<sizeTab; j += i)
      {
        tab[j]=0;
      }
    }
  }
  pthread_exit(NULL);
}

相关问题