首页 > 解决方案 > 使用 C 语言和打开 MP 超过特定矩阵长度时的未定义行为

问题描述

C 程序读取一个矩阵并确定一列的平均值以及该值是否出现在该列中。它适用于小型矩阵,但不适用于中型和大型矩阵。我得到的结果是随机的,即使输入相同,也会从执行变为另一个。顺序版本工作正常。在 C 中是否也有等效于 C++ 折叠指令的指令?我没有收到任何错误或警告

#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);
}

标签: copenmp

解决方案


代码现在可以正常工作

  1. 我将写入移动到并行区域之外的文件。
  2. 使最外层的循环平行而不是嵌套的循环。
  3. 确保删除任何依赖项(我能想到)并在并行循环中初始化变量。
  4. 正确处理文件打开过程和潜在故障
  5. 如果我错过了什么,请告诉我。

#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);
}



推荐阅读