Reputation: 295
I am trying to write a program in C that calculates the series:
for(i=0; i <= n; i++){
(2*i+1)/factorial(2*i);
}
n is the number of elements, determined by the user as an argument. The user also determines the number of threads that are going to calculate the series.
I divide the series in subseries that calculate only a part of the series and each subseries should be calculated by a single thread. The problem is that my threads probably share memory because some series members are calculated many times and others are not calculated at all. Do you know why? Please help!
Here is the problematic part of the code:
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <gmp.h>
#include <math.h>
#include <pthread.h>
/* a struct to pass function arguments to the thread */
struct intervals_struct {
int **intervals;
mpf_t *result;
int thread_index;
};
/* calculate the sum of the elements of the subseries;
doesn't work properly for more than one thread */
void* sum_subinterval(void *args) {
/* Initialize the local variables here */
struct intervals_struct *p = (struct intervals_struct*)args;
for(i=(*p).intervals[(*p).thread_index][0]; i<=(*p).intervals[(*p).thread_index][1]; i++){
/* Do something with the local variables here */
}
mpf_set((*p).result[(*p).thread_index],sum);
/* Free resources used by the local variables here */
}
/* calculate the sum of all subseries */
void main(int argc, char * argv[]){
int p, t, i;
p = atoi(argv[1]);
assert( p >= 0);
t = atoi(argv[2]);
assert( t >= 0);
int **intervals_arr;
intervals_arr = (int**)malloc(t * sizeof(int *));
for(i = 0; i < t; i++) {
intervals_arr[i] = (int *)malloc(2 * sizeof(int));
}
/* Calculate intervals and store them in intervals_arr here */
mpf_t *subinterval_sum;
subinterval_sum = (mpf_t*)malloc(t * sizeof(mpf_t));
for(i=0; i < t; i++) {
mpf_init(subinterval_sum[i]);
}
pthread_t *tid;
tid = (pthread_t *)malloc(t * sizeof(pthread_t));
for(i = 0; i < t; i++) {
struct intervals_struct args = {intervals_arr, subinterval_sum, i};
pthread_create(&(tid[i]), NULL, sum_subinterval, (void*)&args);
}
for(i = 0; i < t; i++) {
pthread_join(tid[i], NULL);
}
/* Sum the elements of the result array and free resources used in main here */
}
Upvotes: 0
Views: 165
Reputation: 137345
The problem is probably here:
for(i = 0; i < t; i++) {
struct intervals_struct args = {intervals_arr, subinterval_sum, i};
pthread_create(&(tid[i]), NULL, sum_subinterval, (void*)&args);
}
You are passing the address of args
to your new thread, but the lifetime of that variable ended immediately after the pthread_create
call. The compiler can and will reuse the stack space occupied by args
between different loop iterations.
Try allocating an array on the heap with malloc
instead.
Edit: What I meant by that last sentence is something like this:
struct intervals_struct * args = (struct intervals_struct *) calloc(t, sizeof(struct intervals_struct));
for(i = 0; i < t; i++) {
args[i].intervals = intervals_arr;
args[i].result = subinterval_sum;
args[i].thread_index = i;
pthread_create(&(tid[i]), NULL, sum_subinterval, (void*)&args[i]);
}
// at the end of main(), or at least after every thread has been joined
free(args);
Upvotes: 3