【问题标题】:Sieve of Eratosthenes with multithreading in C/Linux在 C/Linux 中使用多线程的 Eratosthenes 筛选
【发布时间】:2019-06-10 09:31:48
【问题描述】:

我目前正在使用 C 多线程计算 Eratosthenes Sieve。

目标是首先创建一个主线程,使用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)  

【问题讨论】:

  • for(int i = 0; i &lt; nbThreads; ++i) pthread_create (&amp;threads[i], NULL, SieveEratosthenes, plageThreadi); plageThreadi += nbTachesParThread; 不是你所期望的。另一个很好的例子,为什么要使用自动源格式和/或花括号。
  • 谢谢我已经添加了括号,但我仍然有问题:/

标签: c linux multithreading pthreads


【解决方案1】:

除了my comment here 中提到的问题之外,还有更多需要解决的问题:

首先,PThread 函数必须是void *(*)(void*) 类型。代码使用的类型是void *(*)(int*)。不好。

第二,代码错过了加入工作线程,因此分配线程在创建所有工作线程后结束,然后它加入main(),然后访问工作人员最有可能仍在工作的变量导致未定义行为这样做然后结束,结束过程。结束进程会取消所有工作线程。

【讨论】:

  • 谢谢,根据 2 点我有一些问题: 1:如何将参数传递给 PThread 函数? 2:我只需要在for循环中插入一个pthread_join(threads[i], NULL)?
  • 指 2.:第一次创建 所有 个工人,然后只有 ,第二次加入他们。
  • 参考1.:定义线程特定变量并将其特定的自己的变量的地址传递给每个线程。
  • 感谢您的指点 2 我需要创建 for 循环,一个包含所有创建,另一个包含所有连接
【解决方案2】:

我听从了您的建议,并创建了一个结构来包含所有线程将使用的变量。

但是我注意到有时它可以工作(它很好地显示素数)但有时它不起作用并且它只显示 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);
}

【讨论】:

  • 每个线程都需要一个 separate 结构,否则它们会互相踩踏。
【解决方案3】:

我已经修改了我的代码,所以实际上我没有更多的错误代码,但是一旦我输入了 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);
}

【讨论】:

  • 为什么要在创建循环中加入?
  • 谢谢,我忘了取下来!现在它可以工作了,除了它显示所有数字而不仅仅是素数(尽管我尝试过无线程函数并且效果很好)
  • 第二个例子使用了全局变量。这些由创建者线程和工作人员同时访问。如果访问不受保护,这会导致未定义的行为。保护通常使用互斥锁来完成。但是,为什么不坚持将创建所需的信息传递给每个线程的初始方法呢?
  • 所以实际上我需要把所有的全局变量放到局部变量中?
  • 请在此处查看我之前的评论:stackoverflow.com/questions/56523757/…
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-11
相关资源
最近更新 更多