The C program reads a matrix and determines the average of a column and if that value has occurred in that column. It works with small matrices but it doesn't with medium and large Matrices. The results I get are random and changes from execution to another even if the input is the same. The sequential version works fine. Also is there an equivalent of the C++ collapse directive in C? I got no errors or warnings
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <omp.h>
// user call the application from the command line and
// inputs the length of the square array and the name of the input file
int main(int argc, char **argv)
{
int ii,i, sum = 0, newi = 0, k = 0;
int n, I, J;
int L;
L = atoi(argv[1]);
int size;
size = L * L;
newi = size;
char *str = NULL;
double *d = NULL;
double **ptr;
ptr = &(d);
str = (char *)malloc(sizeof(char)*size);
d = (double*)malloc(sizeof(double)*size);
FILE *fp = argc > 1 ? fopen(argv[2], "r") : stdin;
FILE *fptr = NULL;
float local_sum, *avg;
int matches2;
if (!fp)
{ //validate file open for reading
fprintf(stderr, "error: file open failed '%s'.\n", argv[2]);
return 1;
}
for (i = 1;i < argc;i++)
{
while (fscanf(fp, "%s", str) != EOF)
{
sscanf(str, "%lf", &d[k]);//storing the values as double in a vector
k++;
}
}
if (fp != stdin) fclose(fp); // close file if not stdin
printf("number of elements in the file is %d\n", newi);
printf("number of elements in a row is %d\n", L);
int r = L;
float **arr = (float **)malloc(r * sizeof(float *));
int w = 0;
for (i = 0; i < r; i++)
arr[i] = (float *)malloc(r * sizeof(float));
avg = (float *)malloc(L * sizeof(float *));
//#pragma omp parallel for // This didn't work
for (i = 0; i < L; i++)
{
int j = 0;
//#pragma omp parallel for reduction (+:w) // This didn't work
for ( j = 0; j < L; j++)
{
arr[i][j] = d[w];
//printf(" %lf %d \n \n ", arr[i][j],w);
w += 1;
}
}
// 1 ) finding the average of each column
// 2 ) comparing the indivual values to the average
// 3 ) writing the matching results
// 1 ) finding the average of each column
int j ;
//#pragma omp parallel for
for (j = 0; j < L; j++)
{
local_sum = 0;
#pragma omp parallel for shared (local_sum)
for (i = 0; i < L; i++)
{
local_sum += arr[i][j];
// no data dependency or a race condition
//printf("local sum is %lf\n", local_sum);//delete
//printf("Hello from thread %d of %d in local summation \n ", omp_get_thread_num(), omp_get_num_threads());
}
//control printf("local sum is %lf\n", local_sum);//delete
avg[j] = local_sum / L;// every j is unique to the running threads and there's no race condition
// 2 )comparing the indivual values to the average
int matches = 0;
#pragma omp parallel for shared(matches)
for (i = 0; i < L; i++)
{
if (arr[i][j] == avg[j])
matches++;
//printf("Hello from thread %d of %d in matches calculation now is %d \n ", omp_get_thread_num(), omp_get_num_threads(),matches);
}
//fclose(fp);
//control printf("matches are %d\n", matches);
// 3 )writing the results
matches2 = matches;
omp_set_dynamic(0);
#pragma omp parallel firstprivate(matches2) num_threads(1)
{
if (matches2 >= 1)
{
printf("we have a match in column %d the value matches the average of elements in the column.(%d time/s) \n", j, matches2);
// creating the output file and opening it to Write without deleting previous results
fptr = fopen("D:\\OutputfromFile.txt", "a");
//fptr = fopen(*argv[3], "a"); This did not work !
fprintf(fptr, "We have a match in column %d ", j);// writing results to the file
fprintf(fptr, " , we matched %d time/s\n", matches2);// writing results to the file
//printf("Hello from thread %d of %d \n ", omp_get_thread_num(), omp_get_num_threads());
}
else
{
//if (j+1==L)continue;
//control printf("we have no matches ");
// creating the output file and opening it to Write without deleting previous results
fptr = fopen("D:\\OutputfromFile.txt", "a");
fprintf(fptr, "We have no matches ");// writing results to the file
//fprintf(fptr, " , we matched %d time/s\n", matches);// writing results to the file
//break;
}
}
}
fclose(fptr);
}
The code now works fine
#include <stdio.h>
#include <stdlib.h>
#include <omp.h>
int main(int argc, char **argv)
{
int ii, i, sum = 0, newi = 0, k = 0;
int n, I, J;
int L;
L = atoi(argv[1]);
int size;
size = L * L;
newi = size;
char *str = NULL;
double *d = NULL;
double **ptr;
ptr = &(d);
str = (char *)malloc(sizeof(char)*size);
if (str == NULL) printf(" str memory allocation failed ");
d = (double *)malloc(sizeof(double)*size);
if (d == NULL) printf(" double memory allocation failed ");
FILE *fp = argc > 1 ? fopen(argv[2], "r") : stdin;
FILE *fptr = NULL;
double local_sum, *avg;
int matches2;
int *filearraymatches, *filearraytimes;
filearraymatches = (int *)malloc(L * sizeof(int *));
filearraytimes = (int *)malloc(L * sizeof(int *));
if (!fp)
{ //validate file open for reading
fprintf(stderr, "error: file open failed '%s'.\n", argv[2]);
return 1;
}
for (i = 1;i < argc;i++)
{
while (fscanf(fp, "%s", str) != EOF)
{
//printf("%s\n", str);//just checking
sscanf(str, "%lf", &d[k]);//storing the values as double in a vector
k++;
}
}
if (fp != stdin) fclose(fp); // close file if not stdin
printf("number of elements in the file is %d\n", newi);
printf("number of elements in a row is %d\n", L);
int r = L;
double **arr = (double **)malloc(r * sizeof(double *));
int w = 0;
for (i = 0; i < r; i++)
arr[i] = (double *)malloc(r * sizeof(double));
avg = (double*)calloc(L, sizeof(double));
#pragma omp parallel for default(none)//there is no race condition the variables are all independent
for (i = 0; i < L; i++)
{
int j = 0;
for (j = 0; j < L; j++)
{
arr[i][j] = d[i*L+j];
w += 1;
}
}
// 1 ) finding the average of each column
// 2 ) comparing the individual values to the average
// 3 ) writing the matching results
// 1 ) finding the average of each column
int j;
int matches = 0;
#pragma omp parallel for private(local_sum) private(matches) private(i) default(none)
for (j = 0; j < L; j++)
{
matches = 0;
local_sum = 0;
for (i = 0; i < L; i++)
{
local_sum += arr[i][j];
// no data dependency or a race condition
//printf("local sum is %lf\n", local_sum);//delete
//printf("Hello from thread %d of %d in local summation \n ", omp_get_thread_num(), omp_get_num_threads());
}
avg[j] = local_sum /(double) L;// every j is unique to the running threads and there's no race condition
//printf("local average is %lf\n", avg[j]);//correct calculation
// 2 )comparing the individual values to the average
for (i = 0; i < L; i++)
{
if (arr[i][j] == avg[j])
{ matches++;
//printf("Hello from thread %d of %d in matches calculation now is %d \n ", omp_get_thread_num(), omp_get_num_threads(), matches);
//printf("matches are %d \n", matches);
}
//else printf("matches are %d \n the element is %lf while the average is :%lf", matches, arr[i][j], avg[j]);
;//printf("Hello from thread %d of %d in matches we don't have a match matches: %d \n ", omp_get_thread_num(), omp_get_num_threads(), matches);
//printf("avg[%d]= %lf \n", i, avg[i]);
//printf("arr[i][j] = %lf , average is %lf \n", arr[i][j], avg[j]);
//printf("\n***********************matches are %d\n", matches);
}
// 3 )writing the results
if (matches >0)
{
filearraymatches[j] = j;
filearraytimes[j] = matches;
//printf("we have a match in column %d the value matches the average of elements in the column.(%d time/s the average in the column is %lf ) \n", j, matches, avg[j]);
}
else
{
filearraymatches[j] = 0;
filearraytimes[j] = 0;
}
}
char *path = argv[3];// Output file is a parameter
// Writing results to the file
//fptr = fopen(path, "W");//assertion error
fptr = fopen(path, "w");
if (fptr == NULL)
{
perror(path);
printf(" fileerror ");
exit(EXIT_FAILURE);
}
for (int i = 0;i < L;i++)
{
if (filearraytimes[i] != 0)
{
fprintf(fptr, "We have a match in column %d ", i);// writing results to the file
fprintf(fptr, " , we matched %d time/s\n", filearraytimes[i]);// writing results to the file
}
else fprintf(fptr, " We have no matches in this column %d \n",i);// writing results to the file
}
fclose(fptr);
}