How can i have multiple threads in C working on the same for loop of a two-dimensional array?
Solution 1
You should create an array of per-thread parameters, and pass these to the threads one-by-one. In your case a single pointer to int
is sufficient: you pass to the thread its index threadindex
from zero to NTHREADS
, and the thread passes back the sum for rows such that row % NTHREADS == threadindex
.
Here is how your thread function looks:
void *CalculateSum(void *args)
{
int *argPtr = args;
int i,j,sum = 0;
int threadindex = *argPtr;
for( i = 0; i <= N-1; i++) {
if (i % NTHREADS != threadindex) continue;
for( j = 0; j <= M-1; j++) {
sum += dimensional_array[i][j];
}
}
pthread_mutex_lock( &mutex1 ); Mutex must go here
counter++;
pthread_mutex_unlock( &mutex1 );
// Pass the value back:
*argPtr = sum;
}
main()
{
pthread_t thread_id[NTHREADS];
int thread_args[NTHREADS];
int i, j;
pthread_mutex_init(&mutex1, NULL);
for (i = 0; i <= N - 1; i++ )
for( j = 0; j <= M - 1; j++)
dimensional_array[i][j] = i;
for(i=0; i < NTHREADS; i++)
{
thread_args[i] = i;
pthread_create( &thread_id[i], NULL, CalculateSum, &thread_args[i]);
}
int sum = 0;
for(j=0; j < NTHREADS; j++)
{
pthread_join( thread_id[j], NULL);
sum += thread_args[i];
}
printf("Final counter value: %d. Total: %d\n", counter, sum);
}
Solution 2
To calc the sum of one line (ignoring the thread stuff):
void *CalculateSum(void *dummyPtr)
{
int j,sum = 0;
int i = (int)dummyPtr;
for( j = 0; j <= M-1; j++) {
sum += dimensional_array[i][j];
}
printf(" Sum = %d\n", sum);
pthread_mutex_lock( &mutex1 );
counter++;
pthread_mutex_unlock( &mutex1 );
}
And then create the thread like this:
int line_number = 2; // Or whatever line to print`enter code here`
pthread_create( &thread_id[i], NULL, CalculateSum, (void *)line_number );
EDIT: put "counter++" back in.
programmer
Updated on November 17, 2020Comments
-
programmer over 3 years
i have a program in C.
I have created 3 threads with pthread_create and i have created a mutex in order to lock/unlock the critical regions.
The 3nd argument of pthread_create is a pointer to a function that the thread will execute.
In the examples i've found in the Web, this function is always very simple e.g. prints the thread id or prints a message.
What happens when the function that the thread shall execute contains a for loop?
Cause in my program i would like each one of the threads to work with a two dimensional array.
Each thread shall find the sum of a line of a two-dimensional array. e.g.
Thread1 shall calculate the sum of first line of the 2-dimensional array
Thread2 shall calculate the sum of the second line
Thread1 shall calculate the sum of the 3nd line
Thread3 shall calculate the sum of the 3nd lineI don't care about the order of the threads, but i need every thread to pick one of the lines.
I have the following code that sums two cells in the two dimensional array.
The program:
creates NTHREADS
for(i=0; i < NTHREADS; i++) { pthread_create( &thread_id[i], NULL, CalculateSum, NULL ); }
Each thread waits for the others to finish
for(j=0; j < NTHREADS; j++) { pthread_join( thread_id[j], NULL); }
the function that each thread shall execute but for ONE line of the array and NOT for the WHOLE array is
void *CalculateSum(void *dummyPtr) { pthread_mutex_lock( &mutex1 ); int i,j,sum = 0; for( i = 0; i <= N-1; i++) { for( j = 0; j <= M-1; j++) { sum = dimensional_array[i][j] + dimensional_array[i][j]; } printf(" Sum = %d\n", sum); } counter++; pthread_mutex_unlock( &mutex1 ); }
The whole program is as follows: The program does not have any compilation error.
In order to run it you shall do: gcc -pthread program.c
//program.c #include <stdio.h> #include <pthread.h> #define NTHREADS 3 void *CalculateSum(void *); pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER; int counter = 0; #define N 10 #define M 10 int dimensional_array[N][M]; main() { pthread_t thread_id[NTHREADS]; int i, j; for (i = 0; i <= N - 1; i++ ) for( j = 0; j <= M - 1; j++) dimensional_array[i][j] = i; for(i=0; i < NTHREADS; i++) { pthread_create( &thread_id[i], NULL, CalculateSum, NULL ); } for(j=0; j < NTHREADS; j++) { pthread_join( thread_id[j], NULL); } printf("Final counter value: %d\n", counter); //print ARRAY for (i = 0; i <= N-1; i++ ) { for( j = 0; j <= M-1; j++) printf("%d\t",dimensional_array[i][j]); printf("\n"); } } //Calculate void *CalculateSum(void *dummyPtr) { pthread_mutex_lock( &mutex1 ); int i,j,sum = 0; for( i = 0; i <= N-1; i++) { for( j = 0; j <= M-1; j++) { sum = dimensional_array[i][j] + dimensional_array[i][j]; } printf(" Sum = %d\n", sum); } counter++; pthread_mutex_unlock( &mutex1 ); }
So, i would like each thread to find the sum of a line but i'm confused, i don't know how to do that.
In my program every time a thread calls the Calculate function, all the sum of the lines are computed and not just one
[Caution:For simplicity i sum the first element with it's own,the point is to understand how those threads can all take place in that for loop]
I would be glad if someone could help me
Thanks, in advance
-
MattJenko over 11 yearsThis was going to be my answer, but I think (correct me if I'm wrong) that because each thread is only reading the array then you actually don't need the mutex - making the program run 3 times as fast on a multi-core processor :)
-
Johnny Mopp over 11 yearsYes, I see no need for the mutex either, but apparently it's part of OPs assignment.
-
Johnny Mopp over 11 yearsAfter re-checking it looks like it's there to access the global "counter" variable which I left out.
-
MattJenko over 11 yearsAh yes, I see now. With the 'counter' variable you most definitely do - did you want to put that in @Johnny
-
programmer over 11 yearsI have a problem with the int threadindex argPtr; , i get an error like program.c: In function 'CalculateSum': program.c:23: error: expected '=', ',', ';', 'asm' or 'attribute' before '' token program.c:26: error: 'threadindex' undeclared (first use in this function) program.c:26: error: (Each undeclared identifier is reported only once program.c:26: error: for each function it appears in.)
-
Sergey Kalinichenko over 11 years@programmer Yes, a
=
was indeed missing there.