【问题标题】:Threads being created and joined over and over in for loops (C)在 for 循环中一遍又一遍地创建和连接线程 (C)
【发布时间】:2015-05-03 06:17:54
【问题描述】:

我编写了一个程序,在 C 中执行高斯消元并返回矩阵的 L2 范数。该程序被称为./exec n k,其中 n 是 nxn 矩阵的大小,k 是将用于执行该程序的线程数(最多 4 个)。我运行像 ./gauss 30 4 这样的程序,它会出现段错误。

使用 GDB 后,我发现线程退出的数量比预期的要多,我认为因为我的线程是在 for 循环中创建的,所以它们会被一遍又一遍地连接和创建,从而导致 seg 错误。有人可以指出我正确的方向

#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <omp.h>
#include <time.h>
#include <sys/time.h>
#include <pthread.h>

//globals
double **a, *vect, *bvect, scalar, ratio, sum, delta, *temp;
int i,j,k,ptr, z;
int y,z;
int bvectcount = 0;
int threadcount;
pthread_t workerThreads[4];
typedef struct threader {
    int counter;
    int matrixl;
} threader;
struct timeval start, end;
    void *retval;

int checkargs(int argc, char* argv[]);
// a is matrix, b is vector, x is the solution vector, and n is the size 
double L2(double **a, double *bvect, double *vect, int matrixSize) {
    double sum;
    double res[matrixSize];
    int i, j;
    for (i=0; i < matrixSize; i++) {
        sum = (double) 0;
        for (j=0; j < matrixSize; j++) {
            sum += a[i][j] * vect[j];
        }
        res[i] = sum;
    }
    for (i=0; i < matrixSize; i++) {
        res[i] -= vect[i];
    }
    double squaresum = (double) 0;
    for (i=0; i < matrixSize; i++) {
        squaresum += res[i] * res[i];
    }
    return sqrt(squaresum);
}
int checkargs(int argc, char* argv[]){
    if(argc != 3){
        fprintf(stderr, "Error: Usage is size threadNum\n" );
        exit(1);
    }
}

void *parallelstuff(void *args){
    threader temp = *((threader *)args);
    int i, matrixSize;
    i = temp.counter;
    matrixSize = temp.matrixl;
    double temp2;
    for(j = i + 1; j<matrixSize; j++){
        temp2 = a[j][i]/a[i][i];
        for(z = 0; z<matrixSize + 1; z++){
            a[j][z] = a[j][z] - temp2 * a[i][z];
        }
    }
}
int main(int argc, char* argv[]){
    //check for args
    checkargs(argc, argv);
    int matrixSize = atoi(argv[1]);
    int threadNum = atoi(argv[2]);
    //memory allocation
     a = (double**)malloc(matrixSize*sizeof(double*));
    for(i = 0; i < matrixSize ; i++)
        a[i] = (double*)malloc(matrixSize*sizeof(double) * matrixSize);
    vect = (double*)malloc(matrixSize*sizeof(double));
    bvect = (double*)malloc(matrixSize*sizeof(double));
    temp = (double*)malloc(matrixSize*sizeof(double));
    for(i = 0; i < matrixSize; ++i){
        for(j = 0; j < matrixSize + 1; ++j){
            a[i][j] = drand48(); 
        }
    }
    j = 0;
    j += matrixSize;
    for(i = 0; i < matrixSize; ++i){
        bvect[i] = a[i][j];
    }
//generation of scalar matrix (diagonal vector)
    gettimeofday(&start, NULL);
    for(i=0; i<matrixSize; i++){
        scalar = a[i][i];
    //initialization of p to travel throughout matrix
        ptr = i;
    //find largest number in column and row number of it
        for(k = i+1; k < matrixSize; k++){
        if(fabs(scalar) < fabs(a[k][i])){
            //k is row of scalar, while
           scalar = a[k][i];
           ptr = k;
        }
    }
    //swaping the elements of diagonal row and row containing largest no
    for(j = 0; j <= matrixSize; j++)
    {
        temp[0] = a[i][j];
        a[i][j]= a[ptr][j];
        a[ptr][j] = temp[0];
    }
    ratio = a[i][i];
    for(k = 0; k < matrixSize + 1; k++){
        a[i][k] = a[i][k] / ratio;
    }   
    threader stuff;
    stuff.counter = i;
    stuff.matrixl = matrixSize;
    //MAKE EACH THREAD DO SOMETHING DIFF
    //
    // parallelstuff(int i, int matrixSize, double **a){
    for(threadcount = 0; threadcount < threadNum; threadcount++){
        if(pthread_create (&workerThreads[threadcount], NULL, parallelstuff, (void *) &stuff ) != 0){
            fprintf(stderr, "Error: consumer create problem\n");
            exit(1);
            }
        }
    while(threadcount != 0){
        if(pthread_join (workerThreads[threadcount-1], &retval ) != 0){
        fprintf(stderr, "Error: consumer create problem\n");
        exit(1);
        }
        threadcount--;
    }


    //create matrix of n size 
    //backward substitution method
    for(i=matrixSize-1; i >=0; i--){
        for(k = i; k > 0; k--){
            a[k-1][matrixSize] -= a[k-1][i] * a[i][matrixSize];
            a[k-1][i] -= a[k-1][i] * a[i][i];
        }  
    }
    for(i = 0; i < matrixSize; ++i){
        vect[i] = a[i][matrixSize];
        }       
    double l2Norm;
    l2Norm = L2(a, bvect, vect, matrixSize);
    printf("THIS IS L2 NORM: %f\n", l2Norm);
    gettimeofday(&end, NULL);
    delta = ((end.tv_sec  - start.tv_sec) * 1000000u + 
         end.tv_usec - start.tv_usec) / 1.e6;
    printf("end time: %f\n", delta);
}
        }

终端返回:

(gdb) run 3 4
Starting program: (filepath removed but its there lol)
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib64/libthread_db.so.1".
[New Thread 0x7ffff72fe700 (LWP 32612)]
[Thread 0x7ffff72fe700 (LWP 32612) exited]
[New Thread 0x7ffff6afd700 (LWP 32613)]
[New Thread 0x7ffff62fc700 (LWP 32614)]
[Thread 0x7ffff6afd700 (LWP 32613) exited]
[Thread 0x7ffff62fc700 (LWP 32614) exited]
[New Thread 0x7ffff5afb700 (LWP 32615)]
[Thread 0x7ffff5afb700 (LWP 32615) exited]
[New Thread 0x7ffff72fe700 (LWP 32616)]
[Thread 0x7ffff72fe700 (LWP 32616) exited]
[New Thread 0x7ffff6afd700 (LWP 32617)]
[Thread 0x7ffff6afd700 (LWP 32617) exited]
[New Thread 0x7ffff62fc700 (LWP 32618)]
[Thread 0x7ffff62fc700 (LWP 32618) exited]
[New Thread 0x7ffff5afb700 (LWP 32619)]
[Thread 0x7ffff5afb700 (LWP 32619) exited]
[New Thread 0x7ffff72fe700 (LWP 32620)]
[Thread 0x7ffff72fe700 (LWP 32620) exited]
[New Thread 0x7ffff6afd700 (LWP 32621)]
[Thread 0x7ffff6afd700 (LWP 32621) exited]
[New Thread 0x7ffff62fc700 (LWP 32622)]
[Thread 0x7ffff62fc700 (LWP 32622) exited]
[New Thread 0x7ffff5afb700 (LWP 32623)]
[Thread 0x7ffff5afb700 (LWP 32623) exited]
THIS IS L2 NORM: 0.000000
end time: 0.009503
[Inferior 1 (process 32611) exited normally]
(gdb) 

编辑:我在 GDB 中发现了一些有趣的东西,它可以说明很多问题。这永远循环,然后最终出现段错误。有人可以帮我理解这是什么吗?

http://i.stack.imgur.com/4ZMvx.png

【问题讨论】:

  • 2 种口味?我以前有一个 checkargs 的原型,但我把 checkargs 移到了 main 上面,只是忘了把原型拿出来
  • 哎呀,我错过了;
  • 首先,去掉程序中的所有演员表。它们完全没用,可能只是隐藏错误。然后不要将指针数组用作假矩阵。 C 具有更容易处理的 2D 矩阵内置。像double (*A)[n] = malloc(sizeof(double[n][n])); 这样的东西很容易完成这项工作。您的问题很可能只是您的复杂分配方案。
  • 另外,请正确缩进你的代码,这很难读。
  • 我已经缩进了不合适的行!

标签: c loops for-loop pthreads


【解决方案1】:

这一行

for(j = 0; j < matrixSize + 1; ++j){
    a[i][j] = drand48(); 
}

是错误的,会导致矩阵每一行末尾的访问越界。

您可以查看valgrind 或类似工具来帮助您检测此类越界访问。

【讨论】:

  • 这实际上是一个由于高斯消除的增广矩阵,这是故意的,我怕
  • 有意无意,你不给它分配空间。
  • 我已经修好了。但是,我为这个程序的 OpenMP 版本使用了几乎相同的代码,它运行完美。我知道我的代码是错误的,但它是如何事先工作的?
  • @ericylee314,运气不好。这在很大程度上取决于您分配的大小,通常malloc 在最后分配一点“备用”。正如我在另一条评论中所说,您确实应该转而使用连续矩阵并定期使用 valgrind 之类的工具来检查您的内存访问。如果它对您有帮助,也请考虑接受答案,这会将您的雷达问题放在其他人身上。
  • @MichaelBurr,第二个matrixSize 因素在我回答后被编辑。
【解决方案2】:

以下代码包含有关更改的 cmets。

Note: for clarity and maintainability, only one variable per line
Note: for clarity, all braces are included
Note: added brace at end of main() function that should be elsewhere in the function
Note: there are still two compile problems, as noted in the code:
1) function drand48() not defined
2) parameter bvect in function l2 not used.

Please fix all the remaining problems in the code and re-post

#include <stdlib.h>
#include <stdio.h>
#include <math.h> // sqrt()
#include <omp.h>
#include <time.h> // time() gettimeofday()
#include <sys/time.h>
#include <pthread.h>
#include <string.h> // memcpy()

struct threader
{
    int counter;
    int matrixl;
};

//globals
double **a;
double *vect;
double *bvect;
double scalar;
double ratio;
double sum;
double delta;
double *temp;

int i;
int j;
int k;
int ptr;
int z;
int y;
//int z; <-- second declaration of same variable

int bvectcount = 0; // unused variable

int threadcount;
pthread_t workerThreads[4];

struct timeval start; // beginn execution time
struct timeval end;   // end    execution time

void *retval;

// prototypes
// a is matrix, b is vector, x is the solution vector, and n is the size
double L2(double **a, double *bvect, double *vect, int matrixSize);

// thread function
void *parallelstuff(void *args);

// check command line argumen counts
int checkargs(int argc, char* argv[]);







int main(int argc, char* argv[])
{
    //check for args
    checkargs(argc, argv);

    int matrixSize = atoi(argv[1]);
    if( 0 >= matrixSize )
    {
        // handle error; exit(1);
    }

    int threadNum = atoi(argv[2]);
    if( (0 >= threadNum) || (4 < threadNum) )
    {
        // handle error; exit(1);
    }

    //memory allocation
    if( NULL == (a = malloc(matrixSize*sizeof(double*)) ) )
    {
        // perror(); call cleanup; exit(1);
    }

    for(i = 0; i < matrixSize ; i++)
    {
        if( NULL == (a[i] = malloc(matrixSize*sizeof(double) * matrixSize) ) )
        {
            //perror(); call cleanup; exit(1);
        }
    }


    if( NULL == (vect  = malloc(matrixSize*sizeof(double)) ) )
    {
        // perror(); call cleanup; exit(1);
    }

    if( NULL == (bvect = malloc(matrixSize*sizeof(double)) ) )
    {
        // perror(); call cleanup; exit(1);
    }

    if( NULL == (temp  = malloc(matrixSize*sizeof(double)) ) )
    {
        // perror(); call cleanup; exit(1);
    }

    for(i = 0; i < matrixSize; ++i)
    {
        for(j = 0; j < matrixSize + 1; ++j)
        {
            a[i][j] = drand48(); // where is this function defined?
        }
    }


    j = matrixSize;

    for(i = 0; i < matrixSize; ++i)
    {
        bvect[i] = a[i][j];
    }

    //generation of scalar matrix (diagonal vector)
    gettimeofday(&start, NULL); // time how long this takes to execute

    for(i=0; i<matrixSize; i++)
    {
        scalar = a[i][i];

        //initialization of p to travel throughout matrix
        ptr = i;

        //find largest number in column and row number of it
        for(k = i+1; k < matrixSize; k++)
        {
            if(fabs(scalar) < fabs(a[k][i]))
            {
                //k is row of scalar, while
                scalar = a[k][i];
                ptr = k;
            }
        }

        //swaping the elements of diagonal row and row containing largest no
        for(j = 0; j <= matrixSize; j++)
        {
            temp[0] = a[i][j];
            a[i][j]= a[ptr][j];
            a[ptr][j] = temp[0];
        }

        ratio = a[i][i];

        for(k = 0; k < matrixSize + 1; k++)
        {
            a[i][k] = a[i][k] / ratio;
        }

        struct threader stuff;
        stuff.counter = i;
        stuff.matrixl = matrixSize;

        // parallelstuff(int i, int matrixSize, double **a){

        for(threadcount = 0; threadcount < threadNum; threadcount++)
        {
            if( pthread_create( &workerThreads[threadcount], NULL, parallelstuff, (void *) &stuff ) )
            {
                fprintf(stderr, "Error: consumer create problem\n");
                exit(1);
            }
        }


        while(threadcount != 0)
        {
            if(pthread_join (workerThreads[threadcount-1], &retval ) != 0)
            {
                fprintf(stderr, "Error: consumer create problem\n");
                exit(1);
            }
            threadcount--;
        }

        //create matrix of n size
        //backward substitution method
        for(i=matrixSize-1; i >=0; i--)
        {
            for(k = i; k > 0; k--)
            {
                a[k-1][matrixSize] -= a[k-1][i] * a[i][matrixSize];
                a[k-1][i] -= a[k-1][i] * a[i][i];
            }
        }

        for(i = 0; i < matrixSize; ++i)
        {
            vect[i] = a[i][matrixSize];
        }

        double l2Norm;
        l2Norm = L2(a, bvect, vect, matrixSize);
        printf("THIS IS L2 NORM: %f\n", l2Norm);
        gettimeofday(&end, NULL);
        delta =
            ((end.tv_sec  - start.tv_sec) * 1000000u + end.tv_usec - start.tv_usec) / 1.e6;
        printf("end time: %f\n", delta);

        return(0);
    } // supply missing closing brace, just for testing, where should this actually be placed?
    } // end function: main


double L2(double **a, double *bvect, double *vect, int matrixSize) // unused param: bvect
{
    double sum;
    double res[matrixSize];
    int i;
    int j;

    for (i=0; i < matrixSize; i++)
    {
        sum = 0.0;

        for (j=0; j < matrixSize; j++)
        {
            sum += a[i][j] * vect[j];
        }
        res[i] = sum;
    }

    for (i=0; i < matrixSize; i++)
    {
        res[i] -= vect[i];
    }

    double squaresum = 0.0;

    for (i=0; i < matrixSize; i++)
    {
        squaresum += res[i] * res[i];
    }

    return sqrt(squaresum);
} // end function: L2


// this function changes global array 'a[]'
// to avoid race conditions, a mutex should be used to lock the resource (a[])
//  while it is being modified
void *parallelstuff(void *args)
{
    struct threader temp;    // this shadows global 'temp' variable
    memcpy ( &temp, (struct threader *)args, sizeof(struct threader) );

    int j;
    int z;

    int i = temp.counter;
    int matrixSize = temp.matrixl;

    double temp2 = 0.0;

    for(j = i + 1; j<matrixSize; j++)
    {
        temp2 = a[j][i] / a[i][i];
        for(z = 0; z<matrixSize + 1; z++) // this will access memory beyond the bounds of 2d matrix a[]
        {
            a[j][z] = a[j][z] - temp2 * a[i][z];
        }
    }

    pthread_exit( NULL );
} // end function: parallelstuff


int checkargs(int argc, char* argv[])
{
    if(argc != 3)
    {
        fprintf(stderr, "Error: Usage: %s size threadNum\n", argv[0] );
        exit(1);
    }

    return( 0 );
} // end function: checkargs

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-20
    相关资源
    最近更新 更多