简体   繁体   中英

Display the prime numbers using multi-threading in C

In the function printprime , I am iterating over each element with each of the four threads, this is almost equivalent to a single threaded program. I want to increment i by i=i+MAX_THREADS . I am using four threads as my Laptop has four processors and it is fully optimized. Can someone tell me how to tweak the printprime so that each thread iterates over a single digit. Like, thread 1 checks 2, 6, 10... thread2 checks 3, 7, 11... and so on.

#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;
}

To achieve desirable, increment variable i in function void *printprime(void *ptr) by MAX_THREADS (4 in your case).

Note: Line printf("Thread id[%d] checking [%d]\\n",pthread_self(),i); is used to show that which thread is checking which value.

Following code may be helpful:

#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;
 }

There are multiple problems in your code:

  • all threads use for (i = 2; i < N; i++) so they perform exactly the same scan, testing the same numbers... You get no advantage from using multiple threads.

  • the name printprime is very confusing for a function that scans for prime numbers but does not print them.

  • you modify the same array in multiple threads without synchronisation: this has undefined behavior if the same element is accessed from different threads and if the element size is smaller than the atomic size.

  • even if the code was modified for each thread to test the subset you document in the question, this would be very inefficient as every other threads would end up testing only even numbers.

  • the loop for (j = 2; j <= i / 2; j++) iterates far too long for prime numbers. You should stop when j * j > i , which can be tested as for (j = 2; i / j <= j; j++) .

  • even with this optimisation, trial division is very inefficient to populate the prime_arr array. Implementing a Sieve of Eratosthenes is far superior and much more appropriate for a multithreading approach.

Here is an example:

#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;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM