I work on this but i did not find solution of my problem.
This is my code. This code give an error on pthread_create and pthread_join lines. I tried everything to fix this problem but i cannot do this.
#include <stdio.h>
#include <pthread.h>
#define array_size 1000
#define no_threads 10
float a[array_size];
int global_index = 0;
int sum = 0;
pthread_t mutex_t ,mutex1;
void *slave(void *ignored)
{
int local_index, partial_sum = 0;
do {
pthread_t mutex_t ,lock(mutex1);
local_index = global_index;
global_index++;
pthread_t mutex ,unlock(mutex1);
if (local_index < array_size)
partial_sum += *(a + local_index);
}
while
(local_index < array_size);
pthread_t mutex , lock(mutex1);
sum += partial_sum;
pthread_t mutex_t , unlock(mutex1);
return 0;
}
main()
{
int i;
pthread_t thread_x[10];
pthread_mutex_init(&mutex1, NULL);
for (i = 0; i < array_size; i++)
a[i] = i+1;
for (i = 0; i < no_threads ; i++)
pthread_create(&thread_x[i] , NULL, slave,NULL);
for (i = 0; i < no_threads; i++)
pthread_join(&thread_x[i] , NULL);
printf("The sum of 1 to %d is %d\n", array_size, sum);
}
I have updated your code(pt1.c) I think you are looking for something like this.
#include <stdio.h>
#include <pthread.h>
#define array_size 1000
#define no_threads 10
float a[array_size];
int global_index = 0;
int sum = 0;
pthread_mutex_t mutex1;
void *slave(void *ignored)
{
int local_index, partial_sum = 0;
do {
pthread_mutex_lock(&mutex1);
local_index = global_index;
global_index++;
pthread_mutex_unlock(&mutex1);
if (local_index < array_size)
partial_sum += *(a + local_index);
}
while(local_index < array_size);
pthread_mutex_lock(&mutex1);
sum += partial_sum;
pthread_mutex_unlock(&mutex1);
return 0;
}
main()
{
int i;
pthread_t thread_x[10];
pthread_mutex_init(&mutex1, NULL);
for (i = 0; i < array_size; i++)
a[i] = i+1;
for (i = 0; i < no_threads ; i++)
pthread_create(&thread_x[i] , NULL, slave,NULL);
for (i = 0; i < no_threads; i++)
pthread_join(thread_x[i] , NULL);
printf("The sum of 1 to %d is %d\n", array_size, sum);
}
You should compile this code as
gcc -pthread pt1.c
output :
The sum of 1 to 1000 is 500500
Related
I have just started working with multi-threading in C and I was given a task to create simple sleepsort algorithm. However when I try to run this, nothing is printing. I have no idea what am I doing wrong. Here is my code:
void* sleepSort(void* arr) {
int x = *(int *) arr;
sleep(x);
printf("%d ", x);
return NULL;
}
#define ARR_SIZE 10
#define MAX_ELEMENT 30
int main(void) {
srand(time(NULL));
int arr[ARR_SIZE];
for (int i = 0; i < ARR_SIZE; i++)
arr[i] = rand() % MAX_ELEMENT;
pthread_t threads[10];
for (int i = 0; i < ARR_SIZE; i++)
pthread_create(&threads[i], NULL, sleepSort, &arr[i]);
getchar();
return 0;
}
So, this is my program that calculates matrix determinant using system calls, not good at all, but, the trouble is that when i put in a number bigger than 8 for dimension of matrix, it crashes somehow and i can't figure why it keeps happening. Please, give me some ideas.
The task was to calculate determinant using multithreading. Maybe, the problem is that I exceed max threads? valgrind says that
Use --max-threads=INT to specify a larger number of threads
and rerun valgrind
valgrind: the 'impossible' happened:
Max number of threads is too low
compile it with gcc -g -pthread
#include <stdlib.h>
#include <pthread.h>
#include <math.h>
#include <time.h>
#include <malloc.h>
pthread_mutex_t mutex;
typedef struct {
int **matrix;
int size;
} T_MS;
void* determinant(void *npt) {
T_MS* tmp = (T_MS*) npt;
int i,j;
double det = 0;
pthread_t *array = malloc(sizeof(pthread_t) * tmp->size);
T_MS *mtarr = malloc(sizeof(T_MS) * tmp->size);
if (tmp->size == 1) {
det = tmp->matrix[0][0];
} else if (tmp->size == 2) {
det = tmp->matrix[0][0] * tmp->matrix[1][1] - tmp->matrix[0][1] * tmp->matrix[1][0];
} else {
for (i = 0; i < tmp->size; ++i) {
mtarr[i].matrix = (int **)malloc(sizeof(int *) * tmp->size);
mtarr[i].size = tmp->size - 1;
for (j = 0; j < tmp->size - 1; ++j) {
if (j < i)
mtarr[i].matrix[j] = tmp->matrix[j];
else
mtarr[i].matrix[j] = tmp->matrix[j + 1];
}
pthread_create(&array[i], NULL, determinant, mtarr + i);
}
for (i = 0; i < tmp->size; ++i) {
void *res;
for (j = 0; j < tmp->size - 1; ++j) {
}
pthread_join(array[i], &res);
double x = *(double *)&res;
det += (-1 + 2 * !(i % 2)) * x * tmp->matrix[i][tmp->size - 1];
double answer = *(double*)&det;
free(mtarr[i].matrix);
}
}
free(mtarr);
free(array);
void* ans = *(void **)&det;
return ans;
}
int main(int argc, char const *argv[]) {
srand(time(NULL));
int **matrix;
int n = 0;
int a;
pthread_t tid;
pthread_attr_t attr;
pthread_attr_init(&attr);
printf("Insert the demention of matrix:\n");
scanf("%d", &n);
matrix = (int**)malloc(n * sizeof(int*));
for (int i=0; i<n; ++i)
matrix[i] = (int*)malloc(n * sizeof(int));
printf("Insert matrix:\n");
for (int i = 0; i < n; ++i) {
for (int j = 0; j < n; ++j) {
matrix[i][j]=rand()%15;
//matrix[i][j] = i;
}
}
for (int i = 0; i < n; ++i) {
for (int j = 0; j < n; ++j) {
printf("%d ", matrix[i][j]);
}
printf("\n");
}
T_MS* npt = (T_MS*)malloc(sizeof(T_MS));
npt->matrix = matrix;
npt->size = n;
void *det;
pthread_mutex_init(&mutex, NULL);
pthread_create(&tid, NULL, determinant, npt);
pthread_join(tid, &det);
double answer = *(double*)&det;
printf("Det is: %f\n", answer);
for (int i = 0; i < n; ++i)
free(matrix[i]);
free(matrix);
free(npt);
return 0;
} ```
I am learning pthreads.
Right now I am trying to make the program that writes to one 2d array using multiple pthreads. Each pthread is responsible for only one line of the array. So there is no race or overlap there.
The goal is to make it as fast as possible without using global variables.
The first solution that I implemented was the one that uses a global variable. And it works as intended. Here is the code:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
int **array;
const int NTHREADS = 5;
const int ELEMENTS = 3;
void *worker(void *arg);
void print_array(int **array);
int main()
{
int i, j;
pthread_t* threads = (pthread_t*)malloc(NTHREADS * sizeof(pthread_t));
array = (int**)malloc(sizeof(int*));
for(i = -1; i < NTHREADS; i++)
{
array[i] = (int*)malloc(sizeof(int));
for (j = -1; j < ELEMENTS; j++)
{
array[i][j] = (int)malloc(sizeof(int));
}
}
for (i = 0; i < NTHREADS; i++)
pthread_create(&threads[i], NULL, worker, (void*)i);
for (i = 0; i < NTHREADS; i++)
pthread_join(threads[i], NULL);
print_array(array);
return 0;
}
void *worker(void *arg)
{
int tid = (int)arg;
for (int j = 0; j < ELEMENTS; j++)
array[tid][j] = j;
return (NULL);
}
void print_array(int **array)
{
for (int i = 0; i < NTHREADS; i++)
{
for (int j = 0; j < ELEMENTS; j++)
printf("%d,", array[i][j]);
printf("\n");
}
}
Then I wrote the same program using struct instead of global variable. Here is the code:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
const int NTHREADS = 5;
const int ELEMENTS = 3;
typedef struct s_asd
{
int **array;
int tid;
} t_asd;
void *worker(void *arg);
void print_array(int **array);
int main()
{
pthread_t* threads = (pthread_t*)malloc(NTHREADS * sizeof(pthread_t));
t_asd tmp;
int i, j;
tmp.array = (int**)malloc(sizeof(int*));
for (i = 0; i <= NTHREADS; i++)
{
tmp.array[i] = (int*)malloc(sizeof(int));
for (j = 0; j <= ELEMENTS; j++)
tmp.array[i][j] = (int)malloc(sizeof(int));
}
for (tmp.tid = 0; tmp.tid < NTHREADS; tmp.tid++)
pthread_create(&threads[tmp.tid], NULL, worker, &tmp);
for (i = 0; i < NTHREADS; i++)
pthread_join(threads[i], NULL);
print_array(tmp.array);
return 0;
}
void *worker(void *arg)
{
t_asd *tmp = (t_asd*)arg;
for (int j = 0; j < ELEMENTS; j++)
tmp->array[tmp->tid][j] = j;
return (NULL);
}
void print_array(int **array)
{
for (int i = 0; i < NTHREADS; i++)
{
for (int j = 0; j < ELEMENTS; j++)
printf("%d,", array[i][j]);
printf("\n");
}
}
This one, prints random numbers. I know that I am using the same pointer in all threads, but threads themselves, are not using the same memory area. So why does it prints random numbers?
What is the best solution, without using a global variable?
Update 1.
Output of the second program:
-1413467520,32668,-1413467440,
-1413467584,-1413467568,-1413467552,
-1413467504,-1413467488,-1413467472,
0,1,2,
0,1,2,
Try something like that :
int main()
{
pthread_t* threads = (pthread_t*)malloc(NTHREADS * sizeof(pthread_t));
t_asd tmp;
int i, j;
tmp.array = (int**)malloc(NTHREADS * sizeof(int*));
for (i = 0; i <= NTHREADS; i++)
{
tmp.array[i] = (int*)malloc(ELEMENTS * sizeof(int));
//can be deleted if you want
for (j = 0; j <= ELEMENTS; j++)
tmp.array[i][j] = 0;
}
for (tmp.tid = 0; tmp.tid < NTHREADS; tmp.tid++) {
t_asd *arg = (t_asd *) malloc(sizeof(t_asd));
memcpy(arg, &tmp, sizeof(t_asd)); //will copy the current tid and the pointer to the array in a new memory area
pthread_create(&threads[tmp.tid], NULL, worker, arg);
}
for (i = 0; i < NTHREADS; i++)
pthread_join(threads[i], NULL);
print_array(tmp.array);
return 0;
}
Of course this is an example and you have to free all the allocations
You are passing local variable tmp as an argument to the thread and changing it in a loop at the same time. This is a data race and your threads most probably will operate over the same data.
Convert tmp to an array, fill and pass a corresponding element to a corresponding thread.
So I'm doing homework for my C class and I came across a problem. I want to sync the acess to my global array with pthread_mutex_lock() but it seems that when 2 or more threads try to lock at the same time it just bugs. Here's my code:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <time.h>
#include <string.h>
#include <unistd.h>
#define NUM_THREADS 10
#define VAL 10
int numbers[49];
pthread_mutex_t mutex;
typedef struct {
int start;
int* vec;
} dados;
void* threadFunction(void *arg){
dados* d = (dados*) arg;
int i = 0;
int j = 0;
int count[49];
memset(count, 0, 49);
for(i = 0; i < 49; i++){
for(j = d->start; j < (d->start + VAL); j++) {
if(d->vec[j] == i+1)
count[i] = d->vec[j];
}
}
pthread_mutex_lock(&mutex);
for(i = 0; i < 49; i++) {
numbers[i]+= count[i];
}
pthread_mutex_unlock(&mutex);
free(d);
pthread_exit(NULL);
}
int main(int argc, char** argv){
srand(time(NULL));
/*=============== Threads ================*/
pthread_mutex_init(&mutex, NULL);
pthread_t threads[NUM_THREADS];
/*========================================*/
int vec[NUM_THREADS * VAL];
int i;
for(i = 0; i < NUM_THREADS * VAL; i++)
vec[i] = (int)(rand() % 49 + 1);
for(i = 0; i < NUM_THREADS; i++) {
dados* d = malloc(sizeof(dados));
d->start = i*VAL;
d->vec = vec;
pthread_create(&threads[i], NULL, threadFunction, d);
}
for(i = 0; i < NUM_THREADS; i++)
pthread_join(threads[i], NULL);
pthread_mutex_destroy(&mutex);
for(i = 0 ; i < 49; i++)
printf("NUMERO %d = %d\n", i+1, numbers[i]);
return 0;
}
Two bugs
memset(count, 0, 49);
should be:
memset(count, 0, sizeof(count));
And..
count[i] = d->vec[j];
should be:
count[i]++;
Have some problems with assigning parallel algorithm to prefix sum issue. I am using openMP for parallel implementation. I have the code in c as below.
Result showing:
seqsum[6] = 28 != parallelsum[6] = 34
Please advise. Thanks.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include "omp.h"
#include <string.h>
#define N 10 //33554432 // 2 ^ 25
#define NUM_THREADS 4
void computeparallelprefix(int *iplist, int *_pprefixsum, unsigned long size)
{
int nthr, *z, *x = _pprefixsum;
int i, j, tid, work, lo, hi;
#pragma omp parallel shared(nthr,x,z) private(i,j,tid,work,lo,hi)
{
int prev_sum;
memcpy((void *)x, (void *)iplist, sizeof(int)*size);
// Assume nthr = 2^k
#pragma omp single
{
nthr = omp_get_num_threads();
z = malloc(sizeof(int)*nthr);
}
tid = omp_get_thread_num();
work = size /nthr + (i = tid < size%nthr ? 1 : 0);
lo = (size/nthr)*tid + (i==1 ? tid : size%nthr);
hi = lo + work;
if (hi > size)
hi = size;
// local prefix sum over x
for(i=lo+1; i<hi; i++)
x[i] += x[i-1];
// local prefix sum for tid
z[tid] = x[hi-1];
#pragma omp barrier
// global prefix sum over z
for(j=1; j<nthr; j=2*j) {
if (tid >= j)
z[tid] = z[tid] + z[tid-j];
#pragma omp barrier
}
// Update local prefix sum x
prev_sum = z[tid] - x[hi-1];
for(i=lo;i<hi;i++)
x[i] += prev_sum;
}
free(z);
}
void initlist(int *iplist, unsigned long size)
{
int i;
for ( i = 0; i < size; i++)
iplist[i] = i+1;
// iplist[i] = rand() % 13;
}
void printlist(int *list, unsigned long size)
{
int i;
for(i = 0; i < size; i++) {
printf("%d ", list[i]);
}
printf("\n");
}
void computeseqprefixsum(int *iplist, int *seqprefixsum, unsigned long size)
{
int i;
seqprefixsum[0] = iplist[0];
for(i = 1; i < size; i++) {
seqprefixsum[i] = seqprefixsum[i-1] + iplist[i];
}
}
void checkresults(int *seqsum, int *parallelsum, unsigned long size)
{
int i;
for(i = 0; i < size; i++)
{
if(seqsum[i] != parallelsum[i]) {
printf("seqsum[%d] = %d != parallelsum[%d] = %d\n", i, seqsum[i], i,
parallelsum[i]);
exit(1);
}
}
}
int main(int argc, char *argv[])
{
// seed the rand generator
srand(time(NULL));
double seqstart, seqend, parstart, parend, seqtime, partime;
// initialize list
int *iplist, *seqprefixsum, *pprefixsum ;
iplist = (int*) malloc(sizeof(int) * N);
seqprefixsum = (int*) malloc(sizeof(int) * N);
pprefixsum = (int*) malloc(sizeof(int) * N);
if(iplist == NULL || seqprefixsum == NULL || pprefixsum == NULL) {
printf("memory cannot be allocated\n");
exit(1);
}
initlist(iplist, N);
seqstart = omp_get_wtime();
computeseqprefixsum(iplist, seqprefixsum, N);
seqend = omp_get_wtime();
seqtime = seqend - seqstart;
omp_set_num_threads(NUM_THREADS);
parstart = omp_get_wtime();
computeparallelprefix(iplist, pprefixsum, N);
parend= omp_get_wtime();
partime = parend - parstart;
checkresults(seqprefixsum, pprefixsum, N);
printf("Seq Time : %f, Par Time : %f, Speedup : %f\n", seqtime, partime,
seqtime/partime);
free(iplist); free(seqprefixsum); free(pprefixsum);
return 0;
}
You have the right idea for the prefix sum with your code.
I'm not sure exactly why you don't get the correct result but I cleaned up your code and my version gets the correct result. See the following question for more details parallel-cumulative-prefix-sums-in-openmp-communicating-values-between-thread
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "omp.h"
#define N 11 //33554432 // 2 ^ 25
void computeparallelprefix(int *iplist, int *_pprefixsum, unsigned long size)
{
int nthr, *z, *x = _pprefixsum;
#pragma omp parallel
{
int i;
#pragma omp single
{
nthr = omp_get_num_threads();
z = malloc(sizeof(int)*nthr+1);
z[0] = 0;
}
int tid = omp_get_thread_num();
int sum = 0;
#pragma omp for schedule(static)
for(i=0; i<size; i++) {
sum += iplist[i];
x[i] = sum;
}
z[tid+1] = sum;
#pragma omp barrier
int offset = 0;
for(i=0; i<(tid+1); i++) {
offset += z[i];
}
#pragma omp for schedule(static)
for(i=0; i<size; i++) {
x[i] += offset;
}
}
free(z);
}
int main(void ) {
int *iplist, *pprefixsum ;
iplist = (int*) malloc(sizeof(int) * N);
pprefixsum = (int*) malloc(sizeof(int) * N);
for(int i=0; i<N; i++) iplist[i] = i+1;
for(int i=0; i<N; i++) printf("%d ", iplist[i]); printf("\n");
computeparallelprefix(iplist, pprefixsum, N);
for(int i=0; i<N; i++) printf("%d ", pprefixsum[i]); printf("\n");
for(int i=0; i<N; i++) printf("%d ", (i+1)*(i+2)/2); printf("\n");
return 0;
}