ptheard not working on Ubuntu with matrix - c

this code works correctly on Windows, but does not give results on Ubuntu. What am I supposed to do about it ?
By the way, I use Ubuntu through a virtual machine, but I don't think it has anything to do with it.
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define NUM_THREADS 4
#define MATRIX_SIZE 4
int matrixA[MATRIX_SIZE][MATRIX_SIZE];
int matrixB[MATRIX_SIZE][MATRIX_SIZE];
int matrixSerial[MATRIX_SIZE][MATRIX_SIZE]={0};
int matrixParallel[MATRIX_SIZE][MATRIX_SIZE]={0};
//Randomize matrix A and B
void randomizeMatrixAandMatrixB()
{
int i,j;
for(i=0; i<MATRIX_SIZE;i++)
for(j=0; j<MATRIX_SIZE;j++)
{
matrixA[i][j]=rand() % 10;
matrixB[i][j]=rand() % 10;
}
}
//this void is Matrix2D
void printMatrix2D(int mat2D[MATRIX_SIZE][MATRIX_SIZE])
{
int i, j;
for (i = 0; i < MATRIX_SIZE; i++)
{
for (j = 0; j < MATRIX_SIZE; j++)
{
printf("%d ", mat2D[i][j]);
}
printf("\n");
}
printf("\n");
}
//I created this here serailMatrix
void serialMatrixMultiplication()
{
int row, column,i;
for (row = 0; row < MATRIX_SIZE; row++)
for (column = 0; column < MATRIX_SIZE; column++)
for (i = 0; i < MATRIX_SIZE; i++)
matrixSerial[row][column] += matrixA[row][i] * matrixB[i][column];
}
//int step for multiplyMatrix
int step_i = 0;
void *multiplyMatrix(void*arg )
{
int core=step_i++;
int row, column,i;
for (row = core * MATRIX_SIZE / 4; row < (core + 1) * MATRIX_SIZE / 4; row++){
for (column = 0; column < MATRIX_SIZE; column++){
for (i = 0; i < MATRIX_SIZE; i++) {
matrixParallel[row][column] += matrixA[row][i] * matrixB[i][column];
}
}
}
pthread_exit(NULL);
}
//void paraleleling
void parallelMatrixMultiplication()
{
pthread_t *thread;
int i;
for (i = 0; i < NUM_THREADS; i++) {
int* p;
thread=malloc(sizeof(pthread_t));
pthread_create(thread, NULL, multiplyMatrix, (void*)(p));
}
}
int main (int argc, char *argv[])
{
srand(time(0));
//Randomize
randomizeMatrixAandMatrixB();
printf("Matrix A\n");
printMatrix2D(matrixA);
printf("Matrix B\n");
printMatrix2D(matrixB);
//Serial Matrix Multiplication
serialMatrixMultiplication();
printf("Serial Multiplication\n");
printMatrix2D(matrixSerial);
//Parallel Matrix Multiplication
parallelMatrixMultiplication();
printMatrix2D(matrixParallel);
return 0;
}
What should I do to run these codes in the virtual machine? Where is my mistake in the line of code? Since it works fine on Windows, not on linux, it shows the remaining values as 0 from the first line. For example, when we divide it into 4 threads on a 4x4 matrix, the first row looks like this starting from 0. I guess it's not running threads
For Example:
Serial Multiplaction
144 255 1 2
15 18 5 4
125 14 52 46
14 5 1 3
0 0 0 0
0 0 0 0
0 0 0 0
0 0 0 0

You were lucky it works on windows.
What is missing in you code is synchronisation.
You must wait for threads to finish before displaying the result. You can easily do this with pthread_join
//void paraleleling
void parallelMatrixMultiplication()
{
pthread_t threads[NUM_THREADS];
int params[NUM_THREADS];
int i;
for (i = 0; i < NUM_THREADS; i++) {
params[i] = i;
pthread_create(threads+i, NULL, multiplyMatrix, &params[i]);
}
for (i = 0; i < NUM_THREADS; i++) {
pthread_join(threads[i], NULL);
}
}
As you can see, I also changed the argument given to multiplyMatrix to avoid using step_i: In main thread, an array containing the parameters is prepared.
//int step for multiplyMatrix
void *multiplyMatrix(void*arg )
{
int core=*(int*)arg;
int row, column,i;
for (row = core * MATRIX_SIZE / 4; row < (core + 1) * MATRIX_SIZE / 4; row++){
for (column = 0; column < MATRIX_SIZE; column++){
for (i = 0; i < MATRIX_SIZE; i++) {
matrixParallel[row][column] += matrixA[row][i] * matrixB[i][column];
}
}
}
pthread_exit(NULL);
}
One last thing: if two different threads could modify the same cell in matrixParallel, it would be a good idea to add some mutex.

parallelMatrixMultiplication() kicks off the processing threads then goes straight into printMatrix2D(). You are not waiting for the threads to finish.
You have a memory leak because you are reusing the thread variable in parallelMatrixMultiplication(). You call malloc() but not free().

Related

Found a problem while trying to rotate a matrix 90 degrees n times in C

I got into some problem when I wanted to make a program in C that rotate 90 degrees counterclockwise a matrix that has a different value of row and column. This is the code:
#include <stdio.h>
void swap(int *x, int *y)
{
int temp = *x;
*x = *y;
*y = temp;
}
void transpose(int row, int column, int matrix[row][column])
{
for (int i = 0; i < row; i++)
{
for (int j = i; j < column; j++)
{
swap(&matrix[i][j], &matrix[j][i]);
}
}
}
void reverseColumns(int row, int column, int matrix[row][column])
{
for (int i = 0; i < column; i++)
{
for (int j = 0, k = column - 1; j < k; j++, k--)
{
swap(&matrix[j][i], &matrix[k][i]);
}
}
}
int main()
{
int row, column;
scanf("%d %d", &row, &column);
int matrix[row][column];
for(int i = 0; i < row; i++)
{
for(int j = 0; j < column; j++)
{
scanf("%d", &matrix[i][j]);
}
}
int rotation_times;
scanf("%d", &rotation_times);
rotation_times = rotation_times % 4;
for(int i = 0; i < rotation_times; i++)
{
transpose(row, column, matrix);
reverseColumns(row, column, matrix);
}
for (int i = 0; i < row; i++)
{
for (int j = 0; j < column; j++)
{
printf("%d ", matrix[i][j]);
}
printf("\n");
}
return 0;
}
I wanted to rotate a 2x3 sized matrix 2 times, this is the input:
2 3
1 1 1
2 3 4
2
This is the expected output:
4 3 2
1 1 1
And this is the actual output:
0 0 422510592
4 3 2
I'm trying to see what's wrong by printing 3 rows and 3 columns and this is what I got:
0 0 -2119237632
4 3 2
1 1 1
Does anyone know what happened and how to fix it? Thanks in advance.

Using multiple threads to do matrix Multiplication in C

So, I was trying to write a program to do matrix multiplication using multiple threads and then plot a graph between the time taken and the number of threads used.
I used the following approach:
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <stdlib.h>
#include <time.h>
#include <sys/time.h>
pthread_mutex_t lock;
#define M 200
#define N 300
#define P 400
#define X 2 // Number of Threads
#define RED "\x1b[31m"
#define GREEN "\x1b[32m"
int A[M][N], B[N][P], C[M][P], D[M][P];
int row = 0;
void *matrixMulti(void *arg)
{
pthread_mutex_lock(&lock);
int i = row++;
for (int j = 0; j < P; j++)
{
C[i][j] = 0;
for (int k = 0; k < N; k++)
{
C[i][j] += A[i][k] * B[k][j];
}
}
pthread_exit(NULL);
pthread_mutex_unlock(&lock);
}
void matrixMultiplicationWithoutThreading();
void matrixMultiplicationWithThreading();
void verifyIfBothMatrixAreSame();
int main()
{
int m, n, p;
// A: m*n Matrix, B: n*p Matrix
for (int i = 0; i < M; i++)
for (int j = 0; j < N; j++)
A[i][j] = rand() % 10;
// scanf("%d", &A[i][j]);
for (int i = 0; i < N; i++)
for (int j = 0; j < P; j++)
B[i][j] = rand() % 10;
// scanf("%d", &B[i][j]);
struct timeval start, end;
gettimeofday(&start, NULL);
matrixMultiplicationWithoutThreading();
gettimeofday(&end, NULL);
double time = (end.tv_sec - start.tv_sec) * 1e6;
time = (time + end.tv_usec - start.tv_usec) * 1e-6;
printf("The time taken by simple matrix calculation without threding is %0.6f\n", time);
struct timeval start_th, end_th;
gettimeofday(&start_th, NULL);
matrixMultiplicationWithThreading();
gettimeofday(&end_th, NULL);
time = (end_th.tv_sec - start_th.tv_sec) * 1e6;
time = (time + end_th.tv_usec - start_th.tv_usec) * 1e-6;
printf("The time taken by using the Threading Method with %d threads is %0.6f\n", X, time);
verifyIfBothMatrixAreSame();
}
void matrixMultiplicationWithThreading()
{
pthread_t threads[X];
for (int i = 0; i < X; i++)
{
threads[i] = (pthread_t)-1;
}
// Computation Started:
for (int i = 0; i < M; i++)
{
// At any moment only X threads at max are working
if (threads[i] == (pthread_t)-1)
pthread_create(&threads[i % X], NULL, matrixMulti, NULL);
else
{
pthread_join(threads[i % X], NULL);
pthread_create(&threads[i % X], NULL, matrixMulti, NULL);
}
}
for (int i = 0; i < X; i++)
pthread_join(threads[i], NULL);
// Computation Done:
}
void matrixMultiplicationWithoutThreading()
{
// Computation Started:
for (int i = 0; i < M; i++)
for (int j = 0; j < P; j++)
{
D[i][j] = 0;
for (int k = 0; k < N; k++)
D[i][j] += A[i][k] * B[k][j];
}
// Computation Done:
}
void verifyIfBothMatrixAreSame()
{
for (int i = 0; i < M; i++)
for (int j = 0; j < P; j++)
{
if (C[i][j] != D[i][j])
{
printf(RED "\nMatrix's are not equal something wrong with the computation\n");
return;
}
}
printf(GREEN "\nBoth Matrixes are equal thus verifying the computation\n");
}
Now, this code works sometimes, and sometimes it doesn't, like the result does not match the actual result. Similarly, this code gives a segmentation fault in one of the Linux virtual machines. Also, even when it works correctly, it doesn't give the asymptotically decreasing graph. Instead, the time is almost constant with arbitrary variations with the thread number.
Can someone help with this, like why this is happening? I found multiple solutions to this problem on the internet; some of them don't work (rarely but it happens), but I haven't seen my approach yet; it might be an issue I think. So, can anyone comment on using pthread_create(&threads[i % X], NULL, matrixMulti, NULL), like why this is not a good idea?
EDITED:
I have tried taking the suggestion and optimising the code, I have not done the Matrix multiplication efficient method, as we were asked to do the O(n^3) method, but I have tried doing the threading correctly. Is this correct?
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <stdlib.h>
#include <time.h>
#include <sys/time.h>
#include <math.h>
#define M 2
#define N 2
#define P 2
#define X 40 // Number of Threads
#define RED "\x1b[31m"
#define GREEN "\x1b[32m"
int t = 0; // Computation done by the first usedXFullthreads
int usedXFull = 0;
int A[M][N], B[N][P], C[M][P], D[M][P];
int row = 0;
void *matrixMulti(void *arg)
{
int* l = (int *)arg;
int n = *l;
int i = 0, j = 0, k = 0, comp = 0;
if (n <= usedXFull)
{
i = n * t / (N * P);
j = (n * t - N * P * i) / N;
k = n * t - N * P * i - N * j;
if (n == usedXFull)
comp = M * N * P - usedXFull * t;
else
comp = t;
}
while (comp)
{
if (i == M)
printf(RED "Some fault in the code\n\n");
C[i][j] += A[i][k] * B[k][j];
comp--;
k++;
if (k == N)
{
j++;
if (j == P)
{
i++;
j = 0;
}
k = 0;
}
}
return NULL;
}
void matrixMultiplicationWithoutThreading();
void matrixMultiplicationWithThreading();
void verifyIfBothMatrixAreSame();
int main()
{
int m, n, p;
// A: m*n Matrix, B: n*p Matrix
for (int i = 0; i < M; i++)
for (int j = 0; j < N; j++)
A[i][j] = rand() % 10;
// scanf("%d", &A[i][j]);
for (int i = 0; i < N; i++)
for (int j = 0; j < P; j++)
B[i][j] = rand() % 10;
// scanf("%d", &B[i][j]);
for (int i = 0; i < M; i++)
for (int j = 0; j < P; j++)
C[i][j] = 0;
struct timeval start, end;
gettimeofday(&start, NULL);
matrixMultiplicationWithoutThreading();
gettimeofday(&end, NULL);
double time = (end.tv_sec - start.tv_sec) * 1e6;
time = (time + end.tv_usec - start.tv_usec) * 1e-6;
printf("The time taken by simple matrix calculation without threding is %0.6f\n", time);
struct timeval start_th, end_th;
gettimeofday(&start_th, NULL);
matrixMultiplicationWithThreading();
gettimeofday(&end_th, NULL);
time = (end_th.tv_sec - start_th.tv_sec) * 1e6;
time = (time + end_th.tv_usec - start_th.tv_usec) * 1e-6;
printf("The time taken by using the Threading Method with %d threads is %0.6f\n", X, time);
verifyIfBothMatrixAreSame();
}
void matrixMultiplicationWithThreading()
{
int totalComp = M * N * P; // Total Computation
t = ceil((double)totalComp / (double)X);
usedXFull = totalComp / t;
int computationByLastUsedThread = totalComp - t * usedXFull;
int computationIndex[X];
pthread_t threads[X];
// Computation Started:
for (int i = 0; i < X; i++)
{
computationIndex[i] = i;
int rc = pthread_create(&threads[i], NULL, matrixMulti, (void *)&computationIndex[i]);
if (rc)
{
printf(RED "ERROR; return code from pthread_create() is %d\n", rc);
exit(-1);
}
}
for (int i = 0; i < X; i++)
pthread_join(threads[i], NULL);
// Computation Done:
}
void matrixMultiplicationWithoutThreading()
{
// Computation Started:
for (int i = 0; i < M; i++)
for (int j = 0; j < P; j++)
{
D[i][j] = 0;
for (int k = 0; k < N; k++)
D[i][j] += A[i][k] * B[k][j];
}
// Computation Done:
}
void verifyIfBothMatrixAreSame()
{
for (int i = 0; i < M; i++)
for (int j = 0; j < P; j++)
{
if (C[i][j] != D[i][j])
{
printf(RED "\nMatrix's are not equal something wrong with the computation\n");
return;
}
}
printf(GREEN "\nBoth Matrixes are equal thus verifying the computation\n");
}
There are many issues in the code. Here are some points:
lock is not initialized with pthread_mutex_init which is required (nor freed).
There is no need for locks in a matrix multiplication: work sharing should be preferred instead (especially since the current lock make your code run fully serially).
Using pthread_exit is generally rather a bad idea, at least it is here. Consider just returning NULL. Besides, returning something is mandatory in matrixMulti. Please enable compiler warnings so to detect such a thing.
There is an out of bound of threads[i] in the 0..M based loop.
There is no need to create M threads. You can create 2 threads and divide the work in 2 even parts along the M-based dimension. Creating M threads while allowing only 2 threads to run simultaneously just add more overhead for no reason (it takes time for thread to be created and scheduled by the OS).
It is generally better to dynamically allocate large arrays than using static global C arrays.
It is better to avoid global variables and use the arg parameter so to get thread-specific data.
To design a fast matrix multiplication, please consider reading this article. For example, the ijk loop nest is very inefficient and should really not be used for sake of performance (not efficient in cache). Besides, note you can use a BLAS library for that (they are highly optimized and easy to use) though I guess this is a homework. Additionally, note that you can use OpenMP instead of pthread so to make the code shorter and easy to read.

Going over a matrix while multi-threading

I need to create a program that gets a dynamic matrix and changes it to one dimension, for example 4x4 matrix will give 16 arrays length, where each index has a odd or even number, matching the index itself. The threads needs to go over the matrix at the same time and copy the odd and even numbers to the correct places in the array. The main thread needs to wait for the rest of them to finish before printing the array and every value with its respective thread. It should come out like this
We managed to fix the segmentation fault that kept happening, but now we need to set it so that each thread runs right after the other but instead each thread runs 4 times and then it switches to a different one. How can I change it so it'll run as asked?
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <pthread.h>
#include <math.h>
#define CORE 4
int N;
int odd = 1;
int even = 0;
typedef struct my_thread {
int** matrix;
int* resArray;
int threadId;
int strart_raw;
int strart_cal;
int end_raw;
int end_cal;
int counter;
} my_thread;
void* createArray(struct my_thread* thread);
void main() {
pthread_t th[CORE];
int s_r = 0, s_c, e_r, e_c;
int i, j, lines, columns, * intMatrix;
printf("Type the N for the N*N matrix:\t");
scanf("%d", &N);
int size = N * N;
int result_Array[N * N];
int retcode;
int interval = size / CORE;
int matrix_build_counter = 1;
intMatrix = (int*)malloc(N * N * sizeof(int));
for (i = 0; i < N; ++i)
{
for (j = 0; j < N; ++j)
{
intMatrix[i * N + j] = matrix_build_counter;
matrix_build_counter++;
}
}
printf("The matrix:\n");
for (i = 0; i < N; i++) {
for (j = 0; j < N; j++) {
printf("%d ", intMatrix[i * N + j]);
}
printf("\n");
}
struct my_thread thred_obj_array[CORE];
for (int i = 0; i < CORE; i++) {
thred_obj_array[i].matrix = &intMatrix;
thred_obj_array[i].resArray = result_Array;
thred_obj_array[i].threadId = i;
thred_obj_array[i].strart_raw = (int)((i * N) / CORE);
thred_obj_array[i].end_raw = (int)(((interval * (i + 1)) / N));
thred_obj_array[i].strart_cal = ((interval * i)) % N;
thred_obj_array[i].end_cal = ((interval) * (i + 1));
thred_obj_array[i].counter = (int)floor((interval)*i);
}
for (int i = 0; i < CORE; i++) {
retcode = pthread_create(&th[i], NULL, createArray, &thred_obj_array[i]);
if (retcode != 0) {
printf("Create thread failed with error %d\n", retcode);
}
}
printf("done");
for (int i = 0; i < CORE; i++) {
pthread_join(th[i], NULL);
}
printf("the result array is: ");
for (int i = 0; i < N * N; i++) {
printf("%d ", result_Array[i]);
}
}
void* createArray(struct my_thread* thread) {
int j;
for (int i = thread->strart_raw; i < N; i = i * sizeof(int) * N) {
for (j = thread->strart_cal; j < N; j++) {
printf("I am thread: %d And my value is: %d , (%d,%d)\n", thread->threadId, (*thread->matrix + i * N)[j], i, j);
if (((*thread->matrix + i * N)[j]) % 2 == 0) {
thread->resArray[even] = (*thread->matrix + i * N)[j];
even += 2;
printf("-----%d ---even---\n", even);
}
else {
thread->resArray[odd] = (*thread->matrix + i * N)[j];
odd += 2;
printf("---%d ---odd--\n", odd);
}
(thread->counter)++;
if (thread->counter == thread->end_cal) {
return;
}
}
thread->strart_cal = 0;
}
}

I am using pthreads to speed up my matrix multiplication but not getting correct values

I have to calculate the speed of operation for different threads but the matrix size has to be (1000X1 and 1X1000). I have to calculate this using 1,2,4,8,16,32,64,128,256 and 512 threads.
my program is returning same values for all the resultant matrix. Where do I make changes?
I am using random number generator to fill the matrices and dynamically allocating and freeing the matrices.
I first kept N = 512 but I was getting segmentation fault core dumped error so I increased the N. How can I use different number of threads to calculate the matrix?
For a 1000X1 and 1X1000 matrix the resulatant matrix is all 18 and gets segmentation fault core dump error.
For 100X1 and 1X100 all values are 3 and the same happens
to compile it you have to use -lpthreads and -fopenmp
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <stdlib.h>
// Each thread computes single element in the resultant matrix
void *mult(void *arg)
{
int *data = (int *)arg;
int k = 0, i = 0;
int x = data[0];
for (i = 1; i <= x; i++)
k += data[i] * data[i + x];
int *p = (int *)malloc(sizeof(int));
*p = k;
// Used to terminate a thread and the return value is passed as a pointer
pthread_exit(p);
}
// Driver code
int main()
{
int i, j, k, row1, col1, row2, col2, r, sum, no_of_threads;
printf("Enter the number of rows for matrix 1\n");
scanf("%d", &row1);
printf("Enter the number of columns for matrix 1 \n");
scanf("%d", &col1);
printf("Enter the number of rows for matrix 2 \n");
scanf("%d", &row2);
printf("Enter the number of columns for matrix 2\n");
scanf("%d", &col2);
int **a = (int **)malloc(row1 * sizeof(int *));
for (i = 0; i < row1; i++)
a[i] = (int *)malloc(col1 * sizeof(int));
int **b = (int **)malloc(row2 * sizeof(int *));
for (i = 0; i < row2; i++)
b[i] = (int *)malloc(col2 * sizeof(int));
for (i = 0; i < row1; i++)
{
for (j = 0; j < col1; j++)
{
a[i][j] = (rand() % 9) + 1;
}
}
for (i = 0; i < row2; i++)
{
for (j = 0; j < col2; j++)
{
b[i][j] = (rand() % 9) + 1;
}
}
int N = 1000;
// declaring array of threads of size row1*col2
pthread_t *threads;
threads = (pthread_t *)malloc(N * sizeof(pthread_t));
int count = 0;
int *data = NULL;
for (i = 0; i < row1; i++)
for (j = 0; j < col2; j++)
{
// storing row and column elements in data
data = (int *)malloc((N) * sizeof(int));
data[0] = col1;
for (k = 0; k < col1; k++)
data[k + 1] = a[i][k];
for (k = 0; k < row2; k++)
data[k + col1 + 1] = b[k][j];
}
// creating threads
for (int i = 0; i < 512; i++)
{
std:
pthread_create(&threads[i], NULL,
mult, (void *)(data));
}
printf("RESULTANT MATRIX IS :- \n");
for (i = 0; i < N; i++)
{
void *k;
// Joining all threads and collecting return value
pthread_join(threads[i], &k);
int *p = (int *)k;
printf("%d ", *p);
if ((i + 1) % col2 == 0)
printf("\n");
}
for (int i = 0; i < row1; i++)
{
free(a[i]);
}
for (int i = 0; i < row2; i++)
{
free(b[i]);
}
free(a);
free(b);
free(data);
return 0;
}
EDIT:
How do I send multiple arguments through threads as if I read the matrix in my main function, I am not able to pass the values of rows and columns to my mult function. If I read the matrix in mult function then the threads are not working. How do I get it to multiply?
Your approach is flawed:
the destination matrix is not allocated properly
you pass the same argument to all threads
the threads do not receive any information regarding where to store the result of the scalar product.
You should allocate an argument structure for each thread and pass the source arrays and destination location.
With the current approach, there are row1 * col2 scalar products to compute: if you want to use fixed number of threads, you should construct a list of tasks for each thread to process in order to distribute the word among the threads. It is rather easy to do it statically and since all single computations are equivalent in terms of complexity, dynamic distribution does not seem necessary.
Note however that you must wait for all threads to complete before examining and freeing the results. Freeing the arrays as the threads are potentially still accessing the data is among the many causes for undefined behavior in the posted code.

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

Resources