Im trying to create a multithreaded application in C for Linux with pthreads library that makes an approximation of pi using infinite series with N+1 terms.Variable N and T are passed from the command line. I am using the Nilakantha approximation formula for pi. N is the upper limit of the number sequence to sum and T would be the # of child threads that calculate that sum. For example if I run command "./pie 100 4". The parent thread will create 4 child threads indexed 0 to 3. I have a global variable called vsum that is a double array allocated dynamically using malloc to hold values. So with 4 threads and 100 as the upper bound. My progam should compute:
Thread 0 computes the partial sum for i going from 0 to 24 stored to an element vsum[0]
Thread 1 computes the partial sum for i going from 25 to 49 stored to an element vsum[1]
Thread 2 computes the partial sum for i going from 50 to 74 stored to an element vsum[2]
Thread 3 computes the partial sum for i going from 75 to 99 stored to an element vsum[3]
After each thread makes calculations. The main thread will compute the sum by adding together all numbers from vsum[0] to vsum[T-1].
Im just starting to learn about threads and processes. Any help or advice would be appreciated. Thank you.
Code I wrote so far:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
double *vsum;
int N, T;
void *PI(void *sum) //takes param sum and gets close to pi
{
int upper = (int)sum;
double pi = 0;
int k = 1;
for (int i = (N/T)*upper; i <= (N/T)*(upper+1)-1; i++)
{
pi += k*4/((2*i)*(2*i+1)*(2*i+2));
if(i = (N/T)*(upper+1)-1)
{
vsum[upper] = pi;
}
k++;
}
pthread_exit(0);
}
int main(int argc, char*argv[])
{
T = atoi(argv[2]);
N = atoi(argv[1]);
if (N<T)
{
fprintf(stderr, "Upper bound(N) < # of threads(T)\n");
return -1;
}
int pie = 0;
pthread_t tid[T]; //thread identifier
pthread_attr_t attr; //thread attributes
vsum = (double *)malloc(sizeof(double));//creates dyn arr
//Initialize vsum to [0,0...0]
for (int i = 0; i < T; i++){
{
vsum[i] = 0;
}
if(argc!=2) //command line does not give proper # of values
{
fprintf(stderr, "usage: commandline error <integer values>\n");
return -1;
}
if (atoi(argv[1]) <0) //if its is negative/sum error
{
fprintf(stderr, "%d must be >=0\n", atoi(argv[1]));
return -1;
}
//CREATE A LOOP THAT MAKES PARAM N #OF THREADS
pthread_attr_init(&attr);
for(int j =0; j < T;j++)
{
int from = (N/T)*j;
int to = (N/T)*(j+1)-1;
//CREATE ARRAY VSUM TO HOLD VALUES FOR PI APPROX.
pthread_create(&tid[j],&attr,PI,(void *)j);
printf("Thread %d computes the partial sum for i going from %d to %d stored to an element vsum[%d]\n", j, from, to, j);
}
//WAITS FOR THREADS TO FINISH
for(int j =0; j <T; i++)
{
pthread_join(tid[j], NULL);
}
//LOOP TO ADD ALL THE vsum array values to get pi approximation
for(int i = 0; i < T; i++)
{
pie += vsum[i];
}
pie = pie +3;
printf("pi computed with %d terms in %d threads is %d\n",N,T,pie);
vsum = realloc(vsum, 0);
pthread_exit(NULL);
return 0;
}
Here is the error I dont see that I get on my program: What am I missing here?
^
pie.c:102:1: error: expected declaration or statement at end of input
}
When I try to run my program I get the following:
./pie.c: line 6: double: command not found
./pie.c: line 7: int: command not found
./pie.c: line 8: int: command not found
./pie.c: line 10: syntax error near unexpected token `('
./pie.c: line 10: `void *PI(void *sum) //takes param sum and gets close to pi'
I haven't looked at logic of your code, but I see following programming errors.
Change
pthread_create(&tid[j],&attr,PI,j);
to
pthread_create(&tid[j],&attr,PI,(void *)j);
pthread_create() takes 4th param as void * which is passed to the thread function.
Also fix your thread function PI to use passed parameter as int like
void *PI(void *sum) //takes param sum and gets close to pi
{
int upper = (int)sum; //don't use `atoi` as passed param is int.
...
//your existing code
}
The 3rd error is for line
realloc(vsum, 0);
By passing 0 to re-allocate, you are effectively just freeing vsum, so you can just use free(vsum). If you indeed want to reallocate you should take the new allocated memory returned by the function something like vsum = realloc(vsum, 0);
The Syntax of pthread is
pthread_create(threadId, threadAttribute, callingMethodName, parameters of calling method);
Ex:
void printLetter( void *p)
{
int i=0;
char c=(char *)p;
while (i<10000)
{
printf("%c",c);
}
}
int main()
{
pthread_t thread_id;
char c='x';
pthread_create (&thread_id, NULL, &printLetter, &c);
pthread_join (thread_id, NULL);
return 0;
}
}
Related
I have a school project which requires me to simulate first come first serve using these variables:
Users Input:
Number of Process: 3
Process 1 Arrives at 0 time and requires 5 'resources'
3
1,5,0
2,5,4
3,1,8
However, i can't seem to get past the first 5 'resources'. I'm trying to figure out how to increase PID and repeat but keep time increasing for all these resources. I've created this same program but it only allows for this specific input and I'm trying to make it more versatile so i can choose any number of processes and resources(unit) needed.
#include <stdio.h>
main() {
int n;
printf("Enter the Amount of processes: ");
scanf("%d",&n);
//Variables
int process[n], unit[n], at[n];
int i,time,PID = 1;
int awt, atat,sum,counter;
int x = n;
//Takes and stores the users input into process unit and at
for(i=0;i<n;i++)
{
scanf("%d,%d,%d", &process[i], &unit[i], &at[i]);
}
sum = sum_array(unit,n);
printf("%d\n", sum);
printf("FCFS\n");
printf("Time PID");
for(counter = 0; counter < x; counter++, PID++){
FCFS(time,n,unit,PID);
}
}
int sum_array(int at[], int num_elements){
int x, sum = 0;
for(x=0; x<num_elements;x++){
sum = sum + at[x];
}
return(sum);
}
int FCFS(int time,int n,int unit[], int PID){
for(time = 0, n = 0 ; unit[n] >0 ;time++, unit[n]--){
printf("\n%d ", time);
printf("%d", PID);
}
return;
}
Sample Output:
FCFS
TIME PID
0 1
1 1
2 1
3 1
4 1
5 2
6 2
7 2
8 2
9 2
10 3
Your problems are mostly related to the FCFS function and the loop where you call it.
Try the following:
Initialize time = 0 in the main function
Pass counter instead of n to FCFS in the loop
Return the updated time from FCFS
Don't reset the time and n parameter inside FCFS
Call to FCFS inside for loop:
time = FCFS(time, counter, unit, PID);
Updated FCFS code:
int FCFS(int time,int n,int unit[], int PID)
{
for( ; unit[n] >0 ;time++, unit[n]--)
{
printf("\n%d ", time);
printf("%d", PID);
}
return time;
}
Other than that, there are a number of issues with your code, but it wouldn't really fit into this Q/A to mention them all, so I stick with the necessary things to get your code running for valid example input.
Since this is a homework question, I would encourage you to solve it on your own. Since you have put in some effort on solving this, I am posting the answer below as a spoiler (Note indentation does not work in spoilers). However before seeing the answer here are few suggestions to fix your program:
As mentioned above, passing n does absolutely nothing. Please use a different variable inside the FCFS function.
No need to increment and pass the PID. Since you are putting it in an array, try to get the value from the array.
Instead of n pass counter to the function so that you can index the two arrays.
The for loop inside FCFS makes no sense. It should be for(i=0; i<unit[counter]; i++). time can just be incremented inside the loop.
time needs to be returned to increment properly
And my code:
int time = 0;
int cur_index = 0;
while (cur_index < n) {
int pid = -1;
if (at[cur_index] <= time) {
pid = process[cur_index];
} else {
printf("%d %d\n", time, pid);
time++;
continue;
}
if (pid != -1) {
int r = 0;
for (r = 0; r < unit[cur_index]; r++) {
printf("%d %d\n", time, pid);
time++;
}
}
}
My assignment is to parallelize some provided sequential code that takes an array of numbers and merges it with another array in order to come up with a sorted list. The first step is to initialize the array on each processor, then fill it with values on the root process. Next, I'm supposed to scatter the array out to the other processors so each processor has a chunk of the data for sorting, then sort these small lists locally and then gather them back up with the root process. My problem here is that no matter what I try the scatter won't actually send any data to the other processors. The array in these processors is always full of 0's, whereas the root processor does contain a list of numbers. Anybody care to take a look at my code and tell me what I'm missing?
The original sequential code
#include <mpi.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/**
* Prints a vector without decimal places...
*/
void print_vector(int n, double vector[]) {
int i;
printf("[%.0f", vector[0]);
for (i = 1; i < n; i++) {
printf(", %.0f", vector[i]);
}
printf("]\n");
}
/**
* Just checks sequentially if everything is in ascending order.
*
* Note: we don't care about stability in this sort since we
* have no data attached to the double value, see
* http://en.wikipedia.org/wiki/Sorting_algorithm#Stability
* for more detail.
*/
void test_correctness(int n, double v[]) {
int i;
for (i = 1; i < n; i++) {
if (v[i] < v[i-1]) {
printf("Correctness test found error at %d: %.4f is not < %.4f but appears before it\n", i, v[i-1], v[i]);
}
}
}
/**
* Initialize random vector.
*
* You may not parallelize this (even though it could be done).
*/
void init_random_vector(int n, double v[]) {
int i, j;
for (i = 0; i < n; i++) {
v[i] = rand() % n;
}
}
double *R;
/**
* Merges two arrays, left and right, and leaves result in R
*/
void merge(double *left_array, double *right_array, int leftCount, int rightCount) {
int i,j,k;
// i - to mark the index of left aubarray (left_array)
// j - to mark the index of right sub-raay (right_array)
// k - to mark the index of merged subarray (R)
i = 0; j = 0; k =0;
while (i < leftCount && j < rightCount) {
if(left_array[i] < right_array[j])
R[k++] = left_array[i++];
else
R[k++] = right_array[j++];
}
while (i < leftCount)
R[k++] = left_array[i++];
while (j < rightCount)
R[k++] = right_array[j++];
}
/**
* Recursively merges an array of n values using group sizes of s.
* For example, given an array of 128 values and starting s value of 16
* will result in 8 groups of 16 merging into 4 groups of 32, then recursively
* calling merge_all which merges them into 2 groups of 64, then once more
* recursively into 1 group of 128.
*/
void merge_all(double *v, int n, int s) {
if (s < n) {
int i;
for (i = 0; i < n; i += 2*s) {
merge(v+i, v+i+s, s, s);
// result is in R starting at index 0
memcpy(v+i, R, 2*s*sizeof(double));
}
merge_all(v, n, 2*s);
}
}
void merge_sort(int n, double *v) {
merge_all(v, n, 1);
}
int main(int argc, char *argv[]) {
if (argc < 2) {
// () means optional
printf("usage: %s n (seed)\n", argv[0]);
return 0;
}
int n = atoi(argv[1]);
int seed = 0;
if (argc > 2) {
seed = atoi(argv[2]);
}
srand(seed);
int mpi_p, mpi_rank;
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &mpi_p);
MPI_Comm_rank(MPI_COMM_WORLD, &mpi_rank);
// init the temporary array used later for merge
R = malloc(sizeof(double)*n);
// all MPI processes will allocate a vector of length n, but only
// process 0 will initialize the values. You must distribute the
// values to processes. You will also likely need to allocate
// additional memory in your processes, make sure to clean it up
// by adding a correct free at the end of each process.
double *v = malloc(sizeof(double)*n);
if (mpi_rank == 0) {
init_random_vector(n, v);
}
double start = MPI_Wtime();
// do all the work ourselves! (you should make a better algorithm here!)
if (mpi_rank == 0) {
merge_sort(n, v);
}
double end = MPI_Wtime();
if (mpi_rank == 0) {
printf("Total time to solve with %d MPI Processes was %.6f\n", mpi_p, (end-start));
test_correctness(n, v);
}
MPI_Finalize();
free(v);
free(R);
return 0;
}
The parts I edited
double start = MPI_Wtime();
// do all the work ourselves! (you should make a better algorithm here!)
if (mpi_rank == 0)
{
//Scatter(sendbuf, sendcount, sendtype, recvbuf, recvcount, recvtype, root, comm)
MPI_Scatter(&v, sizeOf, MPI_DOUBLE, &v, sizeOf, MPI_DOUBLE, 0, MPI_COMM_WORLD);
}
if (mpi_rank > 0)
{
//merge_sort(sizeOf, R);
printf("%f :v[0]", v[0]); printf("%s", "\n");
printf("%f :v[1]", v[1]); printf("%s", "\n");
printf("%f :v[2]", v[0]); printf("%s", "\n");
}
if (mpi_rank == 0)
{
//Gather(sendbuf, sendcount, sendtype, recvbuf, recvcount, recvtype, root, comm)
//MPI_Gather(&v, sizeOf, MPI_DOUBLE, test, sizeOf, MPI_DOUBLE, 0, MPI_COMM_WORLD);
//merge(v, test, n, sizeOf);
merge_sort(n, v);
}
double end = MPI_Wtime();
The code should output three values from each processor that isn't the root, but it just gives me 0's. I tried many different parameters inside the scatter function call, to no avail. Almost everything I tried produces the same output found below. Sample output:
0.000000 :v[0]
0.000000 :v[1]
0.000000 :v[2]
Total time to solve with 2 MPI Processes was 0.000052
EDIT: Calling scatter from every process is also something I tried, as it sounds like this is the way you're supposed to call it instead of just calling it from the root. However, then I get a bunch of errors instead of any output at all. Errors look like this:
*** Process received signal ***
Signal: Segmentation fault (11)
Signal code: (128)
Failing at address: (nil)
*** Process received signal ***
Signal: Segmentation fault (11)
Signal code: (128)
Failing at address: (nil)
Something is clearly wrong here. Not sure what I'm doing wrong though.
Been working on this assignment for class. Put this code together but its giving me several errors I'm not able to solve.
Code
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
//global variables
int N, T;
double vsum[T];
//pie function
void* pie_runner(void* arg)
{
double *limit_ptr = (double*) arg;
double j = *limit_ptr;
for(int i = (N/T)*j; i<=((N/T)*(j+1)-1); j++)
{
if(i %2 =0)
vsum[j] += 4/((2*j)*(2*j+1)*(2*j+2));
else
vsum[j] -= 4/((2*j)*(2*j+1)*(2*j+2));
}
pthread_exit(0);
}
int main(int argc, char **argv)
{
if(argc != 3) {
printf("Error: Must send it 2 parameters, you sent %s", argc);
exit(1);
}
N = atoi[1];
T = atoi[2];
if(N !> T) {
printf("Error: Number of terms must be greater then number of threads.");
exit(1);
}
for(int p=0; p<T; p++) //initialize array to 0
{
vsum[p] = 0;
}
double pie = 3;
//launch threads
pthread_t tids[T];
for(int i = 0; i<T; i++)
{
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_create(&tids[i], &attr, pie_runner, &i);
}
//wait for threads...
for(int k = 0; k<T; k++)
{
pthread_join(tids[k], NULL);
}
for(int x=0; x<T; x++)
{
pie += vsum[x];
}
printf("pi computed with %d terms in %s threads is %k\n", N, T, pie);
}
One of the problems I'm having is with the array up top. It needs to be a global variable but it keeps telling me it's not a constant, even when I declare it as such.
Any help is appreciated, with the rest of the code also.
**EDIT: After updating the code using the comments below, here is the new code. I have a few errors still there and would appreciate help dealing with them.
1) Warning: cast from pointer to integer of different size [-Wpointer-to-int-cast] int j = (int)arg;
2)Warning: cast to pointer from integer of different size [Wint - to - pointer - cast] pthread_create(.......... , (void*)i);
NEW CODE:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
//global variables
int N, T;
double *vsum;
//pie function
void* pie_runner(void* arg)
{
long j = (long)arg;
//double *limit_ptr = (double*) arg;
//double j = *limit_ptr;
//for(int i = (j-1)*N/T; i < N*(j) /T; i++)
for(int i = (N/T)*(j-1); i < ((N/T)*(j)); i++)
{
if(i % 2 == 0){
vsum[j] += 4.0/((2*j)*(2*j+1)*(2*j+2));
//printf("vsum %lu = %f\n", j, vsum[j]);
}
else{
vsum[j] -= 4.0/((2*j)*(2*j+1)*(2*j+2));
//printf("vsum %lu = %f\n", j, vsum[j]);
}
}
pthread_exit(0);
}
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]);
vsum = malloc((T+1) * sizeof(*vsum));
if(vsum == NULL) {
fprintf(stderr, "Memory allocation problem\n");
exit(1);
}
if(N <= T) {
printf("Error: Number of terms must be greater then number of threads.\n");
exit(1);
}
for(int p=1; p<=T; p++) //initialize array to 0
{
vsum[p] = 0;
}
double pie = 3.0;
//launch threads
pthread_t tids[T+1];
for(long i = 1; i<=T; i++)
{
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_create(&tids[i], &attr, pie_runner, (void*)i);
}
//wait for threads...
for(int k = 1; k<=T; k++)
{
pthread_join(tids[k], NULL);
}
for(int x=1; x<=T; x++)
{
pie += vsum[x];
}
printf("pi computed with %d terms in %d threads is %.20f\n", N, T, pie);
//printf("pi computed with %d terms in %d threads is %20f\n", N, T, pie);
free(vsum);
}
Values not working:
./pie1 2 1
pi computed with 2 terms in 1 threads is 3.00000000000000000000
./pie1 3 1
pi computed with 3 terms in 1 threads is 3.16666666666666651864
./pie1 3 2
pi computed with 3 terms in 2 threads is 3.13333333333333330373
./pie1 4 2
pi computed with 4 terms in 2 threads is 3.00000000000000000000
./pie1 4 1
pi computed with 4 terms in 1 threads is 3.00000000000000000000
./pie1 4 3
pi computed with 4 terms in 3 threads is 3.14523809523809516620
./pie1 10 1
pi computed with 10 terms in 1 threads is 3.00000000000000000000
./pie1 10 2
pi computed with 10 terms in 2 threads is 3.13333333333333330373
./pie1 10 3
pi computed with 10 terms in 3 threads is 3.14523809523809516620
./pie1 10 4
pi computed with 10 terms in 4 threads is 3.00000000000000000000
./pie1 10 5
pi computed with 10 terms in 5 threads is 3.00000000000000000000
./pie1 10 6
pi computed with 10 terms in 6 threads is 3.14088134088134074418
./pie1 10 7
pi computed with 10 terms in 7 threads is 3.14207181707181693042
./pie1 10 8
pi computed with 10 terms in 8 threads is 3.14125482360776464574
./pie1 10 9
pi computed with 10 terms in 9 threads is 3.14183961892940200045
./pie1 11 2
pi computed with 11 terms in 2 threads is 3.13333333333333330373
./pie1 11 4
pi computed with 11 terms in 4 threads is 3.00000000000000000000
There are numerous problems with that code. Your specific problem is that, in C, variable length arrays (VLAs) are not permitted at file scope.
So, if you want that array to be dynamic, you will have to declare the pointer to it and allocate it yourself:
int N, T;
double *vsum;
and then, in main() after T has been set:
vsum = malloc (T * sizeof(*vsum));
if (vsum == NULL) {
fprintf (stderr, "Memory allocation problem\n");
exit (1);
}
remembering to free it before exiting (not technically required but good form anyway):
free (vsum);
Among the other problems:
1/ There is no !> operator in C, I suspect the line should be:
if (N > T) {
rather than:
if (N !> T) {
2/ To get the arguments from the command line, change:
N = atoi[1];
T = atoi[2];
into:
N = atoi(argv[1]);
T = atoi(argv[2]);
3/ The comparison operator is ==, not =, so you need to change:
if(i %2 =0)
into:
if (i % 2 == 0)
4/ Your error message about not having enough parameters needs to use %d rather than %s, as argc is an integral type:
printf ("Error: Must send it 2 parameters, you sent %d\n", argc-1);
Ditto for your calculation message at the end (and fixing the %k for the floating point value):
printf ("pi computed with %d terms in %d threads is %.20f\n", N, T, pie);
5/ You pass an integer pointer into your thread function but there are two problems with that.
The first is that you then extract it into a double j, which cannot be used as an array index. If it's an integer being passed in, it should be turned back into an integer.
The second is that there is no guarantee the new thread will extract the value (or even start running its code at all) before the main thread changes that value to start up another thread. You should probably just convert the integer to a void * directly rather than messing about with integer pointers.
To fix both those, use this when creating the thread:
pthread_create (&tids[i], &attr, pie_runner, (void*)i);
and this at the start of the thread function:
int j = (int) arg;
If you get warnings or experience problems with that, it's probably because your integers and pointers are not compatible sizes. In that case, you could try something like:
pthread_create (&tids[i], &attr, pie_runner, (void*)(intptr_t)i);
though I'm not sure that will work any better.
Alternatively (though it's a bit of a kludge), stick with your pointer solution and just make sure there's no possibility of race conditions (by passing a unique pointer per thread).
First, revert the thread function to receiving its value by a pointer:
int j = *((int*) arg);
Then, before you start creating threads, you need to create a thread integer array and, for each thread created, populate and pass the (address of the) correct index of that array:
int tvals[T]; // add this line.
for (int i = 0; i < T; i++) {
tvals[i] = i; // and this one.
pthread_attr_t attr;
pthread_attr_init (&attr);
pthread_create (&tids[i], &attr, pie_runner, &(tvals[i]));
}
That shouldn't be too onerous unless you have so many threads the estra array will be problematic. But, if you have that many threads, you're going to have far greater problems.
6/ Your loop in the thread incorrectly incremented j rather than i. Since this is the same area touched by the following section, I'll correct it there.
7/ The use of integers in what is predominantly a floating point calculation means that you have to arrange your calculations so that they don't truncate divisions, such as 10 / 4 -> 2 where it should be 2.5.
That means the loop in the thread function should be changed as follows (including incrementing i as in previous point):
for (int i = j*N/T; i <= N * (j+1) / T - 1; i++)
if(i % 2 == 0)
vsum[j] += 4.0/((2*j)*(2*j+1)*(2*j+2));
else
vsum[j] -= 4.0/((2*j)*(2*j+1)*(2*j+2));
With all those changes, you get a reasonably sensible result:
$ ./picalc 100 101
pi computed with 100 terms in 101 threads is 3.14159241097198238535
Two problems with that array: The first is that T is not a compile-time constant, which it needs to be if you're programming in C++. The second is that T is initialized to zero, meaning the array will have a size of zero and all indexing of the array will be out of bounds.
You need to allocate the array dynamically once you have read T and know the size. In C you use malloc for that, in C++ you should use std::vector instead.
I'm writing a parallel program which uses multiple pthreads to manipulate values in a square matrix until it reaches a specified point. I'm using pthread barriers to signal the threads to start and let main() know when to update the matrix.
Basically, I have two matrices:
readMatrix: contains the current iteration values for writeMatrix to use.
writeMatrix: updated by a calculation run by the thread using readMatrix values.
Once an iteration is done, the read and write matrices are swapped. The loop then moves on using the updated read matrix.
However, there is a problem; on iteration, the read matrix values that have been swapped are not stored.
I am using a struct to pass all pointer variables to the initiated thread:
struct matrixStruct {
double** readMatrix;
double** writeMatrix;
int dimension;
int totalThreads;
int threadNumber;
int lowerBound;
int upperBound;
};
Here is where the threads are initiated in main() and then the working loop which controls the threads, swaps the matrices and checks if it has met the goal yet:
pthread_t threads[totalThreads];
int rc;
long t;
for( t = 0; t < totalThreads; t++)
{
structInstance[t].readMatrix = readMatrix;
structInstance[t].writeMatrix = writeMatrix;
structInstance[t].dimension = dimension;
structInstance[t].totalThreads = totalThreads;
structInstance[t].threadNumber = t;
structInstance[t].lowerBound = t*innerCellAmountByThread;
structInstance[t].upperBound = findUpperBound(t, innerCellAmountByThread, totalThreads, remainderOfCells);
rc = pthread_create(&threads[t], NULL, initiateThread, &structInstance[t]);
if (rc)
{
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-1);
}
}
int precisionCheck = 0;
// Working while loop
while(precisionCheck != 1) {
// Start all threads
pthread_barrier_wait(&barrier1);
// Wait for them to finish
pthread_barrier_wait(&barrier2);
// Swap matrix and then check for precision
double** tempMatrix;
tempMatrix = writeMatrix;
writeMatrix = readMatrix;
readMatrix = tempMatrix;
precisionCheck = verifyPrecision(readMatrix, writeMatrix, precision, dimension);
}
And here is what each thread does:
void *initiateThread(void *structArg) {
struct matrixStruct *structInstance = structArg;
double** readMatrix = structInstance->readMatrix;
double** writeMatrix = structInstance->writeMatrix;
int dimension = structInstance->dimension;
int totalThreads = structInstance->totalThreads;
int threadNumber = structInstance->threadNumber;
int lowerBound = structInstance->lowerBound;
int upperBound = structInstance->upperBound;
printf("threadNumber: %d lower: %d upper: %d\n\n", threadNumber, lowerBound, upperBound);
while(endFlag == 0) {
pthread_barrier_wait(&barrier1);
relaxMatrixWithBounds(readMatrix, writeMatrix, dimension, lowerBound, upperBound);
pthread_barrier_wait(&barrier2);
}
pthread_exit(NULL);
}
So to summarise, I need readMatrix to actually store the updated value on an iteration.
Any help would be greatly appreciated.
Cheers
I am trying to implement the odd-even transposition sorting algorithm in c with multi-threading. The program will receive a file with a line of integers that need to be correctly sorted. I have created the array that the program will work with and I am reading in the data correctly. Although, I am not quite sure how to create the threads right. I know that amount of threads I will need will always be N/2. However the N will not always be 20, so I am handling a finite amount right now. That's a limitation though b/c N will not always be 20. It could be higher. My program is only able to handle twenty right now. I'm also having trouble with the sorting part as well even though I have a function named swap already. The start point function is where this all takes place. I am not sure where to begin on this issue as well.
This is my code so far:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
int list[20];
int n = 20;
int param[10];
pthread_t threads[10];
void readLINE(char *filename);
void do_swap(int R1, int R2);
void display();
void *startPoint( void *arg );
void readLINE(char *filename)
{
FILE* file;
int i,j;
file = fopen(filename,"r");
if(file==NULL)
{
printf("Error: can't open file.\n");
}
else
{
printf("File opened successfully.\n");
i = 0;
while(!feof(file))
{
fscanf(file,"%d", &list[i]);
i++;
}
printf("The numbers are: \n");
for(j=0; j< i-1; j++)
{
printf("%d\n", list[j]);
}
fclose(file);
}
n = i-1;
}
//swap positions of arguments in list array
void swap(int R1, int R2)
{
if (list[R1] > list[R1+1])
{
int temp = list[R1];
list[R1] = list[R2];
list[R2] = temp;
}
}
void display()
{
int count;
for (count = 0; count < n; count++)
{
//cout << list[count] << " " ;
printf("%d ",list[count]);
}
//cout << endl;
printf("\n");
}
void *startPoint( void *arg )
{
int R1 = *(int*)arg;
int count;
for (count = 0; count < n/2; count++)
{
}
return 0;
}
int main(int argc, char** argv)
{
pthread_attr_t tattr;
pthread_attr_init (&tattr);
pthread_attr_setscope(&tattr, PTHREAD_SCOPE_SYSTEM);
readLINE(argv[1]);
printf("list[] presorted:");
display();
//create n/2 threads to do the sorting algorithm
//the parameter to each thread is an int:
//first thread param is 0
//second thread param is 2
//third thread param is 4 etc....
int count;
for (count = 0; count < n/2; count++)
{
param[count] = count*2;
pthread_create( &threads[ count], NULL, startPoint, (void*) ¶m[count]);
}
//wait for all the reads to finish before exiting the program
//otherwise the process would exit and abort all the threads
for (count = 0; count < n/2; count++)
{
pthread_join(threads[count], NULL);
}
//display the sorted state of the list
printf("list[] after sorting: ");
display();
exit(0);
}
It has been roughly 10 years since I wrote standard C code, so forgive any minor errors. I do think I can help you conceptually.
You are allocating your buffers statically. Instead, determine the sizes involved and dynamically allocate the memory you need. Here's a good reference. Basically determine n as you read in the file, and use malloc to allocate list and param based on that value instead of allocating a fixed array.
What specific problem are you having with the sorting part? Do you get a compiler error, runtime error, incorrect sorting result, ...?
UPDATE:
Here's a discussion of serial and parallel sorting that includes an implementation of parallel odd even transition sorting in C.