I have to write two threads. Each one prints 5 even/odd numbers from 1 to 100 like this (odd is impair in French, even is pair).
even 2,4,6,8,10
odd 1,3,5,7,9
even 12,14,16,18,20
odd 13,15,17,19,21
etc...
I wrote this code:
#include <stdio.h>
#include <semaphore.h>
#include <pthread.h>
#define maxi 100
pthread_mutex_t mutex;
sem_t p;
sem_t imp;
int tour = 0;
void *pair(void *arg);
void *impair(void *arg);
int main() {
pthread_t tidp, tidimp;
pthread_mutex_init(&mutex, NULL);
sem_init(&p, 0, 1);
sem_init(&imp, 0, 1);
pthread_create(&tidp, NULL, pair, (void *)2);
pthread_create(&tidimp, NULL, impair, (void *)1);
pthread_join(tidp, NULL);
pthread_join(tidp, NULL);
sem_destroy(&imp);
sem_destroy(&p);
pthread_mutex_destroy(&mutex);
return 0;
}
void *pair(void *arg) {
int i = (int)arg;
int j, l;
// sleep(5);
pthread_mutex_lock(&mutex);
if (!tour) {
tour = 1;
pthread_mutex_unlock(&mutex);
sem_wait(&imp);
} else {
pthread_mutex_unlock(&mutex);
}
for (l = 0; l < maxi; l += 10) {
sem_wait(&p);
printf(" Pair ");
pthread_mutex_lock(&mutex);
for (j = 0; j < 10; j += 2) {
printf(" %4d \t", j + i);
}
pthread_mutex_unlock(&mutex);
printf("\n");
sem_post(&imp);
i += 10;
}
pthread_exit(NULL);
}
void *impair(void *arg) {
int i = (int)arg;
int j, l;
pthread_mutex_lock(&mutex);
if (!tour) {
tour = 1;
pthread_mutex_unlock(&mutex);
sem_wait(&p);
} else {
pthread_mutex_unlock(&mutex);
}
for (l = 0; l < maxi; l += 10) {
sem_wait(&imp);
printf("Impair ");
pthread_mutex_lock(&mutex);
for (j = 0; j < 10; j += 2) {
printf(" %4d \t", j + i);
}
pthread_mutex_unlock(&mutex);
printf("\n");
sem_post(&p);
i += 10;
}
pthread_exit(NULL);
}
What I don't understand is that when I run the code, sometimes it starts with odd, sometimes with even. More particularly, when it starts with odd everything goes normal and I get the all numbers from 1 to 100, but when it starts with even sometimes I only get to 91, sometimes 93, sometimes 97.
Can anyone tell me what is wrong? The screenshots below might help.
You're not waiting for both threads to exit:
pthread_join(tidp, NULL);
pthread_join(tidp, NULL);
One of those should be tidimp.
Related
I implemented in parallel an algorithm which finds and prints all the circular prime numbers within the interval [2, X]. I measured the execution time of the problem varying the number of threads from 1 to 16. Can someone explain why I get worse execution time when the number of threads is even? (Note: actually I get worse time for an odd number of threads if the main thread is also taken into account)
The processor of the machine I ran the program is "Intel® Core™ i7-8550U", with 4 cores and hyperthreading.
This is the function which the threads are executing (I performed load balancing):
void *printIfCircularPrime(void *threadId)
{
int tid = (int)threadId;
printf("Hi, I am thread %d\n", threadId);
for (long i = 2 + tid; i <= X; i += NR_THREADS)
{
if (isCircularPrime(i))
{
printf("%ld\n", i);
}
}
pthread_exit(NULL);
}
These are my execution time measurements:
Full code:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <math.h>
#include <time.h>
#define NR_THREADS 16
#define X 120000000
int isPrime(long n)
{
if (n <= 1)
{
return 0;
}
if (n == 2)
{
return 1;
}
if (n % 2 == 0)
{
return 0;
}
for (int d = 3; d <= floor(sqrt(n)); d += 2)
{
if (n % d == 0)
{
return 0;
}
}
return 1;
}
int countDigits(long n)
{
int digits = 0;
while (n)
{
n /= 10;
digits++;
}
return digits;
}
long cyclicallyPermute(long n, int numberOfDigits)
{
int lastDigit = n % 10;
return pow(10, numberOfDigits - 1) * lastDigit + n / 10;
}
int isCircularPrime(long n)
{
int numberOfDigits = countDigits(n);
for (int i = 0; i < numberOfDigits; i++)
{
if (!isPrime(n))
{
return 0;
}
n = cyclicallyPermute(n, numberOfDigits);
}
return 1;
}
void *printIfCircularPrime(void *threadId)
{
int tid = (int)threadId;
printf("Hi, I am thread %d\n", threadId);
for (long i = 2 + tid; i <= X; i += NR_THREADS)
{
if (isCircularPrime(i))
{
printf("%ld\n", i);
}
}
pthread_exit(NULL);
}
int main(int argc, char *argv[])
{
printf("Number of threads: %d\n", NR_THREADS);
pthread_t threads[NR_THREADS];
struct timespec start, stop;
clock_gettime(CLOCK_REALTIME, &start);
for (int i = 0; i < NR_THREADS; i++)
{
pthread_create(&threads[i], NULL, printIfCircularPrime, (void *)i);
}
for (int i = 0; i < NR_THREADS; i++)
{
pthread_join(threads[i], NULL);
}
clock_gettime(CLOCK_REALTIME, &stop);
printf("\nExecution time: %ld seconds\n", stop.tv_sec - start.tv_sec);
pthread_exit(NULL);
}
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;
}
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
Finishing up an assignment here. Got the code to work and calculate pie except for random values where I receive the following errors:
./piesync 10 3
pi computed with 10 terms in 3 threads is 3.14183961892940200045
* Error in `./piesync': free(): invalid next size (fast): 0x0000000001ca3010 *
./piesync 100 5
* Error in `./piesync': double free or corruption (out): 0x0000000000ee5040 *
I know it might be something with the array or the mutex but cant figure out what.
Code:
//Pini Vaknine
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
//global variables
int N, T;
double gpie = 3.0;
pthread_mutex_t mutex;
//pie function
void* pie_runner(void* arg)
{
long j = (long)arg;
long lower = (N/T)*(j-1)+1;
long upper = ((N/T)*(j));
double myPartialSum = 0;
//printf("lower=%lu upper=%lu\n",lower , upper);
for(long i = lower; i <= upper; i++)
{
if(i % 2 == 0){
myPartialSum -= 4.0/((2*i)*(2*i+1)*(2*i+2));
//printf("vsum %lu = %f\n", j, vsum[j]);
}
else{
myPartialSum += 4.0/((2*i)*(2*i+1)*(2*i+2));
//printf("vsum %lu = %f\n", j, vsum[j]);
}
}
pthread_mutex_lock (&mutex);
gpie = gpie + myPartialSum;
pthread_mutex_unlock (&mutex);
pthread_exit(0);
//return NULL;
}
int main(int argc, char **argv)
{
if(argc != 3) {
printf("Error: Must send it 2 parameters, you sent %d\n", argc-1);
exit(1);
}
N = atoi(argv[1]);
T = atoi(argv[2]);
if(N <= T) {
printf("Error: Number of terms must be greater then number of threads.\n");
exit(1);
}
//launch threads
pthread_attr_t attr;
pthread_t *tids = (pthread_t *) calloc(T, sizeof(pthread_t));
if(tids == NULL) {
fprintf(stderr, "Memory allocation problem\n");
exit(1);
}
pthread_mutex_init(&mutex, NULL);
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
for(long i = 1; i<=T; i++)
{
int r = pthread_create(&tids[i], &attr, pie_runner, (void*)i);
if(r<0) {
printf("ERROR: pthread_create() returned %d\n", r);
exit(2);
}
}
//wait for threads...
for(int k = 1; k<=T; k++)
{
pthread_join(tids[k], NULL);
}
printf("pi computed with %d terms in %d threads is %.20f\n", N, T, gpie);
pthread_mutex_destroy(&mutex);
pthread_attr_destroy(&attr);
free(tids);
return 0;
}
You are indexing out of range of an array. You have allocated an array for T elements here
pthread_t *tids = (pthread_t *) calloc(T, sizeof(pthread_t));
but you index it incorrectly, here
for(int k = 1; k<=T; k++)
{
pthread_join(tids[k], NULL);
}
and other instances too. In C you index an array from 0 so the loop should be
for(int k=0; k<T; k++)
You have a division by zero in
if(i % 2 == 0){
myPartialSum -= 4.0/((2*i)*(2*i+1)*(2*i+2));
for j=0.
Fixing this
for(long i = lower; i <= upper; i++)
{
if(i % 2 == 0){
if ( ((2*i)*(2*i+1)*(2*i+2)) == 0)
myPartialSum = 0.0;
else
myPartialSum -= 4.0/((2*i)*(2*i+1)*(2*i+2));
}
else{
myPartialSum += 4.0/((2*i)*(2*i+1)*(2*i+2));
}
}
and changing the indices, the program works out of the box
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]++;