簡體   English   中英

在C中使用多線程顯示質數

[英]Display the prime numbers using multi-threading in C

在 function printprime中,我用四個線程中的每一個迭代每個元素,這幾乎相當於一個單線程程序。 我想將i增加i=i+MAX_THREADS 我正在使用四個線程,因為我的筆記本電腦有四個處理器並且已經過全面優化。 有人能告訴我如何調整printprime以便每個線程迭代一個數字。 例如,線程 1 檢查 2、6、10... 線程 2 檢查 3、7、11... 等等。

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

#define N 30
#define MAX_THREADS 4

int prime_arr[N] = { 0 };

void *printprime(void *ptr) {
    int j, flag;
    int i = (int)(long long int)ptr;
    for (i = 2; i < N; i++) {
        flag = 0;
        for (j = 2; j <= i / 2; j++) {
            if (i % j == 0) {
                flag = 1;
                break;
            }
        }

        if (flag == 0) {
            prime_arr[i] = 1;
        }
    }
}

int main() {
    pthread_t tid[MAX_THREADS] = {{ 0 }};
    int count = 0;
    for (count = 0; count < MAX_THREADS; count++) {
        printf("\r\n CREATING THREADS %d", count);
        pthread_create(&tid[count], NULL, printprime, (void *)count);
    }
    printf("\n");
    for (count = 0; count < MAX_THREADS; count++) {
        pthread_join(tid[count], NULL);
    }

    int c = 0;
    for (count = 0; count < N; count++)
        if (prime_arr[count] == 1)
            printf("%d ", count);

    return 0;
}

為了達到理想效果, void *printprime(void *ptr)函數void *printprime(void *ptr)的變量i遞增MAX_THREADS (在您的情況下為4)。

注意:printf("Thread id[%d] checking [%d]\\n",pthread_self(),i); 用於顯示哪個線程正在檢查哪個值。

以下代碼可能會有所幫助:

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

#define N 30
#define MAX_THREADS 4

int prime_arr[N]={0};

void *printprime(void *ptr)
{
    int  j,flag;
    int i=(int)(long long int)ptr;
    while(i<N)
    {
        printf("Thread id[%d] checking [%d]\n",pthread_self(),i);
        flag=0;
        for(j=2;j<=i/2;j++)
        {
            if(i%j==0)
            {
                flag=1;
                break;
            }
        }

        if(flag==0 && (i>1))
        {
            prime_arr[i]=1;
        }
        i+=MAX_THREADS;
  }
}

int main()
{
    pthread_t tid[MAX_THREADS]={{0}};
    int count=0;
    for(count=0;count<MAX_THREADS;count++)
    {
        printf("\r\n CREATING THREADS %d",count);
        pthread_create(&tid[count],NULL,printprime,(void*)count);
    }
    printf("\n");
    for(count=0;count<MAX_THREADS;count++)
    {
        pthread_join(tid[count],NULL);
    }

    int c=0;
    for(count=0;count<N;count++)
        if(prime_arr[count]==1)
            printf("%d ",count);

    return 0;
 }

您的代碼中存在多個問題:

  • 所有線程都使用for (i = 2; i < N; i++)所以它們執行完全相同的掃描,測試相同的數字......使用多個線程沒有任何優勢。

  • 對於掃描質數但不打印質數的 function,名稱printprime非常令人困惑。

  • 您在沒有同步的情況下在多個線程中修改同一個數組:如果從不同線程訪問同一元素並且元素大小小於原子大小,則這具有未定義的行為。

  • 即使為每個線程修改了代碼以測試您在問題中記錄的子集,這也會非常低效,因為所有其他線程最終只會測試偶數。

  • for (j = 2; j <= i / 2; j++)的循環對於素數來說迭代的時間太長了。 你應該在j * j > i時停止,這可以通過for (j = 2; i / j <= j; j++)來測試。

  • 即使進行了這種優化,試驗除法填充prime_arr數組的效率也非常低。 實施埃拉托色尼篩法要優越得多,也更適合多線程方法。

這是一個例子:

#include <stdio.h>
#include <stdint.h>
#include <pthread.h>

#define N 10000000
#define MAX_THREADS 4

unsigned char prime_arr[N];

void *scanprime(void *ptr) {
    int n, i, j, flag, start, stop;
    n = (int)(intptr_t)ptr;
    start = N / MAX_THREADS * n;
    stop = N / MAX_THREADS * (n + 1);
    if (start < 2)
        start = 2;
    if (n == MAX_THREADS - 1)
        stop = N;
    for (i = start; i < stop; i++) {
        flag = 1;
        for (j = 2; i / j >= j; j++) {
            if (i % j == 0) {
                flag = 0;
                break;
            }
        }
        prime_arr[i] = flag;
    }
    return NULL;
}

void *sieveprimes(void *ptr) {
    int n, i, j, start, stop;
    n = (int)(intptr_t)ptr;
    /* compute slice boundaries */
    start = N / MAX_THREADS * n;
    stop = N / MAX_THREADS * (n + 1);
    /* special case 0, 1 and 2 */
    if (n == 0) {
        prime_arr[0] = prime_arr[1] = 0;
        prime_arr[2] = 1;
        start = 3;
    }
    if (n == MAX_THREADS - 1) {
        stop = N;
    }
    /* initialize array slice: only odd numbers may be prime */
    for (i = start; i < stop; i++) {
        prime_arr[i] = i & 1;
    }
    /* set all multiples of odd numbers as composite */
    for (j = 3; j * j < N; j += 2) {
        /* start at first multiple of j inside the slice */
        i = (start + j - 1) / j * j;
        /* all multiples below j * j have been cleared already */
        if (i < j * j)
            i = j * j;
        /* only handle odd multiples */
        if ((i & 1) == 0)
            i += j;
        for (; i < stop; i += j + j) {
            prime_arr[i] = 0;
        }
    }
    return NULL;
}

int main() {
    pthread_t tid[MAX_THREADS] = { 0 };
    int i;
    for (i = 0; i < MAX_THREADS; i++) {
        printf("Creating thread %d\n", i);
        pthread_create(&tid[i], NULL, sieveprimes, (void *)(intptr_t)i);
    }
    for (i = 0; i < MAX_THREADS; i++) {
        pthread_join(tid[i], NULL);
    }

    int count = 0;
    for (i = 0; i < N; i++) {
        count += prime_arr[i];
        //if (prime_arr[i] == 1)
        //    printf("%d\n", i);
    }
    printf("%d\n", count);
    return 0;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM