I am trying to fill 2 matrices from 2 data text files but the compiler is telling me I have conflicting types for the "infiles" (1&2) but if I take out FILE I get a casting error and if I take out infile =fopen i get no output at all for matrices but it does compile. nothing seems to work right
the problem code:
FILE *infile1;
FILE *infile2;
*infile1 = (int)fopen("m1.dat","r");
*infile2 = (int)fopen("m2.dat","r");
full code:
#include <stdlib.h>
#include <math.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <pthread.h>
#define M 4
#define K 4
#define N 4
void *runner(void *param); /* the thread */
int A [M][K];
int B [K][N];
int C [M][N];
struct v {
int i; // row
int j; // column
};
int main(int argc, char *argv[]) {
//using namespace std;
//ifstream infile1 ("m1.dat");
//ifstream infile2 ("m2.dat");
int infile1 = (int)fopen("m1.dat","r");
int infile2 = (int)fopen("m2.dat","r");
FILE *infile1;
FILE *infile2;
//if (!infile1) //testing files
// cerr << "Error: could not open input file 1\n";
//if (!infile2) //testing files
//cerr << "Error: could not open input file 2\n";
if (!infile1) //testing files
fprintf(stderr, "file 1 missing\n");
exit(1);
if (!infile2) //testing files
fprintf(stderr, "file 2 missing\n");
exit(1);
int i, j, size1, size2 =0;
//infile1 >> size1;
//infile2 >> size2;
fscanf(infile1,"%d",&size1);
fscanf(infile2,"%d",&size2);
float s = (float)size1;
int dim = (int)sqrt(s);
for(i=0;i<M;i++){
for(j=0;j<N;j++){
//infile1 >> A[i][j];
// infile2 >> B[i][j];
fscanf(infile1,"%d",&A[i][j]);
fscanf(infile2,"%d",&B[i][j]);
}
}
for(i=0;i<M;i++){
for(j=0;j<N;j++){
if ((j % dim)==0) printf("\n");
printf("%d \t",A[i][j]);
}
}
printf("\n\n");
for(i=0;i<M;i++){
for(j=0;j<N;j++){
if ((j % dim)==0) printf("\n");;
printf("%d \t",B[i][j]);
}
}
printf("\n\n");
int count = 0;
for(i = 0; i < M; i++) { //column
for(j = 0; j < N; j++) { //row
//Assign a row and column for each thread
struct v *data = (struct v *) malloc(sizeof(struct v));
data->i = i;
data->j = j;
// Now create the thread passing it data as a parameter
pthread_t tid; //Thread ID
pthread_attr_t attr; //Set of thread attributes
//Get the default attributes
pthread_attr_init(&attr);
//Create the thread
pthread_create(&tid,&attr,runner,data);
//Make sure the parent waits for all thread to complete
pthread_join(tid, NULL);
count++;
}
}
//Print out the resulting matrix
for(i = 0; i < M; i++) {
for(j = 0; j < N; j++) {
printf("%d ", C[i][j]);
}
printf("\n");
}
printf("\n \n");
fclose(infile1);
fclose(infile2);
return 0;
}
//The thread will begin control in this function
void *runner(void *param) {
struct v *data = (struct v*)param; // the structure that holds our data
int n, sum = 0; //the counter and sum
//Row multiplied by column
for(n = 0; n< K; n++){
sum += A[data->i][n] * B[n][data->j];
}
//assign the sum to its coordinate
C[data->i][data->j] = sum;
pthread_exit(0);
}
Edit: Latest version of code. Still just outputs nothing to the screen. Even have a printf that should run right before it closes and that doesnt even work. The only thing I did change from a working versiion(it used to do it correctly) was that the things related to the opening of the file were in C++ and I changed it to C. No idea why I don't get any errors though. Here is my latest full code. the output looks like this http://tinypic.com/r/21185u9/9
#include <stdlib.h>
#include <math.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <pthread.h>
#define M 4
#define K 4
#define N 4
void *runner(void *param); /* the thread */
int A [M][K];
int B [K][N];
int C [M][N];
struct v {
int i; // row
int j; // column
};
int main(int argc, char *argv[]) {
FILE *infile1 = fopen("m1.dat","r");
FILE *infile2 = fopen("m2.dat","r");
if (infile1 == NULL) //testing files
//if (!infile1) //testing files
//fprintf(stderr, "file 1 missing\n");
perror("File 1 Missing");
exit(1);
if (infile2 == NULL) //testing files
//if (!infile1) //testing files
//fprintf(stderr, "file 1 missing\n");
perror("File 2 Missing");
exit(1);
int i, j, size1, size2 =0;
fscanf(infile1,"%d",&size1);
fscanf(infile2,"%d",&size2);
float s = (float)size1;
int dim = (int)sqrt(s);
for(i=0;i<M;i++){
for(j=0;j<N;j++){
fscanf(infile1,"%d",&A[i][j]);
fscanf(infile2,"%d",&B[i][j]);
}
}
for(i=0;i<M;i++){
for(j=0;j<N;j++){
if ((j % dim)==0) printf("\n");
printf("%d \t",A[i][j]);
}
}
printf("\n\n");
for(i=0;i<M;i++){
for(j=0;j<N;j++){
if ((j % dim)==0) printf("\n");;
printf("%d \t",B[i][j]);
}
}
printf("\n\n");
int count = 0;
for(i = 0; i < M; i++) { //column
for(j = 0; j < N; j++) { //row
//Assign a row and column for each thread
struct v *data = (struct v *) malloc(sizeof(struct v));
data->i = i;
data->j = j;
// Now create the thread passing it data as a parameter
pthread_t tid; //Thread ID
pthread_attr_t attr; //Set of thread attributes
//Get the default attributes
pthread_attr_init(&attr);
//Create the thread
pthread_create(&tid,&attr,runner,data);
//Make sure the parent waits for all thread to complete
pthread_join(tid, NULL);
count++;
}
}
//Print out the resulting matrix
for(i = 0; i < M; i++) {
for(j = 0; j < N; j++) {
printf("%d ", C[i][j]);
}
printf("\n");
}
printf("\n \n");
printf("program ran");
fclose(infile1);
fclose(infile2);
return 0;
}
//The thread will begin control in this function
void *runner(void *param) {
struct v *data = (struct v*)param; // the structure that holds our data
int n, sum = 0; //the counter and sum
//Row multiplied by column
for(n = 0; n< K; n++){
sum += A[data->i][n] * B[n][data->j];
}
//assign the sum to its coordinate
C[data->i][data->j] = sum;
pthread_exit(0);
}
Your error comes from declaring the return value from the file open function incorrectly.
Instead of using your problem code, use:
FILE *infile1 = fopen("m1.dat","r");
FILE *infile2 = fopen("m2.dat","r");
It declares infile1 and infile2 as pointers to the FILE type with the values properly set depending on how successful the file can be opened. In simple terms, call infile1 and infile2 as file handles.
If you want an integer value as the return value, you can look into the open() function instead of fopen(), but fopen() works well in your case.
If you check the exit status of your edited code, you will find that it is 1 due to exiting after the first file check. In your code you have:
if (infile1 == NULL) //testing files
//if (!infile1) //testing files
//fprintf(stderr, "file 1 missing\n");
perror("File 1 Missing");
exit(1);
Which will run the exit(1) function every time (even if infile1 is OK). You need to properly contain exit within the scope of your check with {...}. e.g.:
if (infile1 == NULL) { //testing files
perror ("File 1 Missing");
exit (1);
}
and the same for infile2. I have not checked the remainder of your code.
Related
During this lockdown period, you are playing Ludo with your n number of family members where, n<=4. Assume that all the tokens are in the starting square and consider following scenarios: If the outcome of the dice is 6(six), then you can move your one token and get the chance to play dice again; otherwise, you can move your one token and give the dice to the next
player. Think of the players as processes which should be synchronized. You are
required to write a code for it using semaphore.
What I've tried is:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
sem_t *S;
pthread_mutex_t mutex;
int *play, n;
void check(int pid) {
six:
int num = (rand() % 6) + 1;
printf("Player %d rolled and got %d\n", pid + 1, num);
if(num == 6) goto six;
sem_post(&S[pid]); //only for next()
}
void roll(int pid) {
pthread_mutex_lock(&mutex);
check(pid);
pthread_mutex_unlock(&mutex);
sem_wait(&S[pid]);
}
void next(int pid) {
pthread_mutex_lock(&mutex);
int next = (pid+1)%n;
printf("Player %d passed the die to %d\n", pid + 1, next + 1);
check(next);
pthread_mutex_unlock(&mutex);
}
void *player(void *num) {
for (int i = 0; i < n; i++) {
roll(*((int *)num));
next(*((int *)num));
}
}
int main() {
printf("Enter No. of players : ");
scanf("%d",&n);
pthread_t pid[n];
pthread_mutex_init(&mutex, NULL);
S = malloc(n*sizeof(sem_t));
play = malloc(n*sizeof(int));
for(int i = 0; i < n; i++){
play[i] = i;
sem_init(&S[i], 0, 0);
}
for (int i = 0; i < n; i++)
pthread_create(&pid[i], NULL, player, &play[i]);
for (int i = 0; i < n; i++)
pthread_join(pid[i], NULL);
pthread_mutex_destroy(&mutex);
for (int i = 0; i < n; i++)
sem_destroy(&S[i]);
return 0;
}```
This is the output : https://i.stack.imgur.com/ZaNUC.png
I want to rectify the sequence by making the one rolling person is the one whom the die is passed.
I am currently working on the calculation of the Eratosthenes Sieve using C multithreading.
The goal is to first create a main thread that uses a split function to divide the exploration of the numbers on a number of threads.
#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;
}
}
}
}
I tried to implement a code but I have an error at runtime:
segmentation error (core dumped)
On top of the issue mention in my comment here there is more to fix:
1st of all a PThread function needs to be of type void *(*)(void*). The ones used by the code are of type void *(*)(int*). Not good.
2ndly the code misses to join the work-threads, therefore the distributing thread ends after having created all workers, then it gets joined in main(), which then accesses the variables the workers are most likely are still working on causing undefined behaviour be doing so and then ends, ending the process. Ending the process cancels all worker-threads.
I followed your advice and created a structure to contain the variables that will be used by all threads.
However I noticed that sometimes it works (it displays the prime numbers well) but sometimes it doesn't work and it displays either only 0 or all the numbers from 0 to 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);
}
In the main() function, move the calls to pthread_create() and pthread_join() outside of the if statement. These calls should be made regardless of whether or not the pthread_create() call succeeds.
In the SieveEratosthenes() function, the loop that marks composite numbers as 0 should start from i * i, not i. This is because any composite number can be written as the product of two prime numbers, and one of those prime numbers must be less than or equal to the square root of the composite number. Therefore, if a number i is composite, it must have a prime factor less than or equal to the square root of i.
In the creat_thread() function, move the call to pthread_join() inside the loop that creates the threads. This will ensure that each thread has completed before the next one is created.
In the creat_thread() function, initialize the plageThreadPrecedent variable to 2, since this is the first prime number.
I've modified my code so actually I have no more error code but once I have entered the 2 variables (number to calculate + number of threads), the program runs but displays nothing.
#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);
}
I'm working on a project (NOT HOMEWORK), building a multi-thread sudoku solution validator in C. I'm new to C so excuse the bad code quality as I'm still improving.
I want to call the method row_check 9 times from 9 separate threads. For the method as parameters I pass the row number (arg) and array name (arr). I have created the thread but I'm unsure how to pass the parameters properly to the method. Can anyone help me with this?
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
void* row_check(void* arg, int *arr)
{
int i = *((int *)arg); //trying to convert row number to int
int j, flag;
while(i < 9)
{
flag=0x0000;
for(j = 0; j < 9; j++)
flag |= 1 << (arr[i][j]-1);
if (flag != 0x01FF)
report("row", i, j-1);
}
}
void report(char *s, int i, int j)
{
printf("\nThe sudoku is INCORRECT");
printf("\nin %s. Row:%d,Column:%d", s, i+1, j+1);
getch();
exit(0);
}
int main(int argc, char* argv[])
{
int i,j;
char arr1[9][9];
FILE *file = fopen(argv[1], "r");
if (file == 0)
{
fprintf(stderr, "failed");
exit(1);
}
int col=0, row=0;
int num;
while(fscanf(file, "%d ", &num) == 1)
{
arr1[row][col] = num;
col++;
if(col == 9)
{
row++;
col = 0;
}
}
fclose(file);
pthread_t tid;
pthread_attr_t attr;
pthread_attr_init(&attr);
int n;
for(n=0; n < 9; n++) //creating 9 threads
{
pthread_create(&tid, &attr, row_check, n);
pthread_join(tid, NULL);
}
return 0;
}
The thread entry function has to be of the format void *(*start_routine) (void *), which means it receives only one parameter - pointer to anything you like.
The most used technique is to define a struct with the values you want to pass to the thread entry function. Create a variable of that type, initialize it and pass its address to the thread entry function.
Example:
typedef thread_data_s
{
char *ptr;
int row_num; // I would prefer to define it as `unsigned int` but I stick to your example
// + any other data you want to pass to the thread
} thread_data_t;
....
thread_data_t data[NUM_OF_THREADS];
....
for(n=0; n < NUM_OF_THREADS; n++) //creating 9 threads
{
data[n].ptr = &arr1[n][0];
data[n].row_num = n;
pthread_create(&tid, &attr, row_check, &data[n]);
}
...
for(n=0; n < NUM_OF_THREADS; n++) // waiting for all the threads here
{
pthread_join(tid, NULL);
}
And your entry function should look something like this:
void* row_check(void* data)
{
//int i = *((int *)arg); //trying to convert row number to int
thread_data_t *my_data_ptr = data;
int j, flag;
while(i < 9)
{
flag=0x0000;
for(j = 0; j < 9; j++)
flag |= 1u << ( (my_data_ptr->ptr)[my_data_ptr->row_num][j] - 1 );
// Shouldn't it be under the `for` loop block? If so, please add `{}` to the `for` loop
if (flag != 0x01FF)
report("row", my_data_ptr->row_num, j-1);
}
return NULL;
}
I'm working on a small program of multithreaded matrix multiplication. My first job is to fill the entry of matrices with a random integer. I met some segment faults after I tried to pass a function pointer to pthread_create. And I think the problem is in function pthread_join.
But there are two issues in general.
The first one is the segment fault does not happen every time. Sometimes the code works, but most of the times it doesn't. So it really confuses me.
The other one is when the code is working, there are always several entries still not initialized, especially for matrix[0][0], it is never initialized. And I don't quite know where to debug that one.
Here's my code:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include <pthread.h>
#define N 5
#define MAX 10
int A[N][N];
int B[N][N];
int C[N][N];
pthread_t pid[N][N];
typedef struct {
int row, col;
} Pos;
typedef void* (*thread_func)(void*);
void print_matrix(int M[][N]) {
int i, j;
for (i = 0; i < N; i++) {
for (j = 0; j < N; j++) {
printf("%3d", M[i][j]);
if (j < N - 1) {
printf(", ");
}
}
printf("\n");
}
}
void join_threads(void) {
int i, j;
for (i = 0; i < N; i++) {
for (j = 0; j < N; j++) {
pthread_join(pid[i][j], NULL);
}
}
}
void* fill_entry(void* arg) {
Pos* pos = (Pos*)arg;
A[pos->row][pos->col] = rand() % MAX;
B[pos->row][pos->col] = rand() % MAX;
return NULL;
}
void dispatch_jobs(thread_func job_func) {
int i, j;
for (i = 0; i < N; i++) {
for (j = 0; j < N; j++) {
Pos pos;
pos.row = i;
pos.col = j;
if (pthread_create(&pid[i][j], NULL, job_func, (void*)&pos)) {
perror("pthread_create");
exit(-1);
}
}
}
}
int main(void) {
srand(time(NULL));
dispatch_jobs(&fill_entry);
join_threads();
printf("Matrix A:\n");
print_matrix(A);
printf("Matrix B:\n");
print_matrix(B);
return 0;
}
Pos pos;
pos.row = i;
pos.col = j;
if (pthread_create(&pid[i][j], NULL, job_func, (void*)&pos)) {
perror("pthread_create");
exit(-1);
}
You are passing a pointer to a local variable to the threads. Once the thread tries to access the data, i.e. dereferences the pointer, the variable is long gone, reused, and contains garbage data.
I was trying to write a program that calculates prime numbers using threads and the program was working but not giving the desired results (it was telling all numbers were prime numbers). Today I tried to run the program again and I'm getting a segmentation fault even though I didn't alter my program. I tried using gdb to find when it was happening and I think it's happening on the pthread_join function.
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
int n_threads; // number of threads
int* numbers; // array of numbers
int elements_per_thread;
int isPrime(int n){
int i = 0;
for(i=0; i < n; i++)
if(n%i == 0)
return 0;
return 1;
}
void * threadPrime(void * arg){
int* idxp = (int*)arg;
int idx = *idxp;
int start = idx* elements_per_thread;
int finish = (idx+1)*elements_per_thread-1;
int i;
for(i=start; i<finish; i++)
if(!isPrime(i))
numbers[i]=0;
pthread_exit(NULL);
}
int main(int argc, char* argv[]) {
if (argc != 3) {
printf("usage: %s largest_number number_threads\n", argv[0]);
return 1;
}
int largest_number = atoi(argv[1]); // value of the largest number to test for primality
int n_numbers = largest_number-1; // number of numbers to test
n_threads = atoi(argv[2]);
// create and fill vector of numbers to test
numbers = (int *)malloc(n_numbers*sizeof(int)) ; // allocate a vector for n_numbers integers
int i;
for (i = 2; i <= largest_number; i++)
numbers[i-2] = i;
int* id = (int *)malloc(n_threads*sizeof(int));
// compute primes
pthread_t* thid = (pthread_t *)malloc(n_threads*sizeof(int));
for(i=0;i<n_threads;i++){
id[i] = i;
if(pthread_create(&thid[i],NULL,threadPrime,(void*)(id+i)) != 0){
printf("Erro\n");
exit(0);
}
}
for(i=0;i<n_threads;i++){
if(pthread_join(thid[i],NULL) != 0){
printf("Erro\n");
exit(0);
}
}
// print result
printf("Primes:");
int n_primes = 0;
for (i = 0; i < n_numbers; i++)
if (numbers[i]) {
n_primes++;
printf (" %d", numbers[i]);
}
printf("\nTotal: %d primes\n", n_primes);
return 0;
}
Problem solved. Correct code below.
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
int n_threads; // number of threads
int* numbers; // array of numbers
int elements_per_thread;
int isPrime(int n){
int i = 0;
for(i=2; i < n; i++)
if(n%i == 0)
return 0;
return 1;
}
void * threadPrime(void * arg){
int* idxp = (int*) arg;
int idx = *idxp;
int start = idx*elements_per_thread;
int finish = (idx+1)*elements_per_thread;
int i;
for(i=start; i<=finish; i++)
if(!isPrime(numbers[i]))
numbers[i]=0;
pthread_exit(NULL);
}
int main(int argc, char* argv[]) {
if (argc != 3) {
printf("usage: %s largest_number number_threads\n", argv[0]);
return 1;
}
int largest_number = atoi(argv[1]); // value of the largest number to test for primality
int n_numbers = largest_number-1; // number of numbers to test
n_threads = atoi(argv[2]);
// create and fill vector of numbers to test
numbers = (int *)malloc(n_numbers*sizeof(int)) ; // allocate a vector for n_numbers integers
int i;
for (i = 2; i <= largest_number; i++)
numbers[i-2] = i;
int* id;
id = (int *)malloc(n_threads*sizeof(int));
// compute primeselements_per_thread = n_numbers/n_threads;
elements_per_thread = (n_numbers/n_threads)+1;
pthread_t* thid = malloc(n_threads*sizeof(*thid));
for(i=0;i<n_threads;i++){
id[i] = i;
if(pthread_create(&thid[i],NULL,threadPrime,(void*)(id+i)) != 0){
printf("Erro\n");
exit(0);
}
}
for(i=0;i<n_threads;i++){
if(pthread_join(thid[i],NULL) != 0){
printf("Erro\n");
exit(0);
}
}
// print result
printf("Primes:");
int n_primes = 0;
for (i = 0; i < n_numbers; i++)
if (numbers[i]) {
n_primes++;
printf (" %d", numbers[i]);
}
printf("\nTotal: %d primes\n", n_primes);
return 0;
}
There are a number of issues:
1) The starting index for the loop should be 2. Otherwise, you are going to have divide by zero error here:
for(i=0; i < n; i++) // should be i=2
if(n%i == 0)
return 0;
2) elements_per_thread is not set at all. So it's going to be 0 (since it's a global variable) and the loops in thread function will never be called. Set it in main():
elements_per_thread = n_numbers/n_threads;
3) When you call isPrime() you are passing i. But you really wanted to pass numbers[i]. You also want to include the finish in the primality test. So it should be
for(i=start; i<=finish; i++)
if(!isPrime(numbers[i]))
numbers[i]=0;
4) The allocation for thread array is wrong. It should be
pthread_t* thid = malloc(n_threads * sizeof *thid);
There are more efficient ways to test primes (e.g. you only need to check upto n/2 to see if it's prime). But once you fix the above issues, you'll have a working code and think about improving it later.
You didn't allocate the right amount of memory for thid. This is the main reason for your segmentation fault.
pthread_t* thid = (pthread_t *)malloc(n_threads*sizeof(int));
should be
pthread_t* thid = malloc(n_threads*sizeof(p_thread));
(you don't need to cast malloc in C)
This is why I don't usually use an explicit type as the operand of sizeof, and instead just use the variable name so that the compiler can deduce the type itself.
pthread_t* thid = malloc(n_threads*sizeof(*thid));