使用pthread库时的分段错误

时间:2015-09-30 19:29:08

标签: c multithreading

我是线程的新手,我正在尝试使用c中的线程将旅行商问题(动态编程)的顺序程序更改为并行程序。

#include <stdio.h>
#include <limits.h>

#define size 10 //maximum 10 cities
#define min(a,b) (a > b ? b : a)
#define sizePOW  1024    // 2^10

//Space complexity: O(n * 2^n)
//Time complexity: O(n^2 * 2^n)

int n; npow;
int g[size][sizePOW];
int p[size][sizePOW];
int adj[size][size];

int compute(int start, int set) {
    int masked, mask, temp, i;
    int result = INT_MAX; //result stores the minimum 

    if (g[start][set] != -1) //memoization DP top-down,check for repeated subproblem
        return g[start][set];

    for (i = 0; i < n; i++) {   //npow-1 because we always exclude "home" vertex from our set
            mask = (npow - 1) - (1 << i);  //remove ith vertex from this set
            masked = set & mask;
            if (masked != set) { //in case same set is generated(because ith vertex was not present in the set hence we get the same set on removal) eg 12&13=12
                temp = adj[start][i] + compute(i, masked); //compute the removed set
                if (temp < result)
                    result = temp, 
                    p[start][set] = i; //removing ith vertex gave us minimum
            }
        }
        return g[start][set] = result; //return minimum
}
void getpath(int start, int set) {
    if (p[start][set] == -1) 
       return; //reached null set

    int x = p[start][set];
    int mask = (npow - 1) - (1 << x);
    int masked = set & mask; //remove p from set
    printf("%d ", x);
    getpath(x, masked);
}
void TSP() {    
    int i, j;
    //g(i,S) is length of shortest path starting at i visiting all vertices in S and ending at 1
    for (i = 0; i < n; i++)
        for (j = 0; j < npow; j++) 
                g[i][j] = p[i][j] = -1; 
    for (i = 0; i < n; i++)
         g[i][0] = adj[i][0]; //g(i,nullset)= direct edge between (i,1)

    int result = compute(0, npow - 2);//npow-2 to exclude our "home" vertex
    printf("Tour cost:%d\n", result);
    printf("Tour path:\n0 ");
    getpath(0, npow - 2);
    printf("0\n");
}

int main(void) {
    int i, j;
    printf("Enter number of cities\n");
    scanf("%d",&n);
    npow=(int)pow(2, n);//bit number required to represent all possible sets
    printf("Enter the adjacency matrix\n");
    for(i = 0; i < n; i++)
       for(j = 0; j < n; j++)
          scanf("%d", &adj[i][j]);
    TSP();
    return 0;
}

这是来自ideone code的顺序程序。 这是我的

的并行代码
#include <stdio.h>
#include <math.h>
#include <pthread.h>
#include <signal.h>
#include <errno.h>
#include <unistd.h>
#include<limits.h>

#define size 10 //maximum 10 cities
#define min(a,b) a > b ? b:a
#define sizePOW 1024 // 2^10

struct threadargs {
    int a, b;
    int *c;
};
//Space complexity: O(n * 2^n)
//Time complexity: O(n^2 * 2^n)

int n, npow;
int g[size][sizePOW];
int p[size][sizePOW];
int adj[size][size];

void printMatrix() {
    int i, j;
    for (i = 0; i < 4; i++) {
        for (j = 0; j < 16; j++) {
            printf("%d ",g[i][j]);

        printf("\n");
    }
    printf("\n\n");
}

void *compute(void *args) { 
    int masked, mask, i, start, set; 
    int result = INT_MAX; //result stores the minimum 
    struct threadargs *recvargs = (struct threadargs *) args;
    start = recvargs->a;
    set = recvargs->b;
    int *retval = recvargs->c;

    if (g[start][set] != -1) { //memoization DP top-down,check for repeated subproblem
        *retval += g[start][set];
        return;
    }

    printMatrix();
    //sleep(1);
    int temp[n];

    for (i = 0; i < n; i++)
        temp[i] = INT_MAX;

    pthread_t threads[n];
    struct threadargs arguments[n];
    int running_thread_count = 0;

    for (i = 0; i < n; i++) 
       threads[i] == -1;

    for (i = 0; i < n; i++) {   //npow-1 because we always exclude "home" vertex from our set
            mask= (npow - 1) - (1 << i); //remove ith vertex from this set
            masked = set & mask;
            //printf("hello world");
            if (masked != set)//in case same set is generated(because ith vertex was not present in the set hence we get the same set on removal) eg 12&13=12
            {   
                temp[i] = adj[start][i];
                arguments[i].a = i;
                arguments[i].b = masked;
                arguments[i].c = &temp[i];
                pthread_create(&threads[i], NULL, compute, (void *)&arguments[i] );
                running_thread_count++;

            }
        }

        for (i = 0; i < n; i++) {
            if (pthread_kill(threads[i], 0) != ESRCH)
                pthread_join(threads[i], NULL);
        }

        int ith = 0;
        result = temp[0];
        for (i = 1; i < n; i++) {
            if(temp[i] < result) {
                result = temp[i];
                ith = i;
            }
        }
        p[start][set] = ith;
        if (result != INT_MAX)
            g[start][set] = result; //return minimum
        *retval += g[start][set];
}

void getpath(int start,int set)
{
    if (p[start][set] == -1)
       return; //reached null set
    int x = p[start][set];
    int mask= (npow - 1) - (1 << x);
    int masked = set & mask;//remove p from set
    printf("%d ",x);
    getpath(x, masked);
}
void TSP()
{   int i, j;
    //g(i,S) is length of shortest path starting at i visiting all vertices in S and ending at 1
    for(i=0; i < n; i++)
        for( j = 0; j < npow; j++) 
                g[i][j] = p[i][j] = -1; 
    for (i = 0; i < n; i++)
        g[i][0] = adj[i][0]; //g(i,nullset)= direct edge between (i,1)

    int result;
    struct threadargs arguments;
    arguments.a = 0;
    arguments.b = npow-2;
    arguments.c = &result;
    compute((void *) &arguments);//npow-2 to exclude our "home" vertex
    printf("Tour cost:%d\n",result);
    printf("Tour path:\n0 ");
    getpath(0,npow-2);
    printf("0\n");
}
int main(void) {
    int i, j;
    printf("Enter number of cities\n");
    scanf("%d", &n);
    npow=(int)pow(2, n);//bit number required to represent all possible sets
    printf("Enter the adjacency matrix\n");
    for (i = 0; i < n; i++)
       for (j = 0; j < n; j++)
            scanf("%d", &adj[i][j]);
    TSP();
    return 0;
}

但是我在尝试执行此代码时遇到了分段错误。以下是gdb的输出

Program received signal SIGSEGV, Segmentation fault.
0x00007ffff78bf63e in pthread_join (threadid=4196128, 
    thread_return=0x0) at pthread_join.c:85
85  pthread_join.c: No such file or directory.
(gdb) backtrace
#0  0x00007ffff78bf63e in pthread_join (threadid=4196128, 
    thread_return=0x0) at pthread_join.c:85
#1  0x0000000000400b36 in compute (args=0x7fffffffde90) at tsp3.c:69
#2  0x0000000000400db2 in TSP () at tsp3.c:107
#3  0x0000000000400ec8 in main () at tsp3.c:120
(gdb) 

我知道这不会给任何明显的性能提升,但我想试试这个。提前谢谢。

**编辑:** 我已经纠正了错误,但现在我遇到了新的错误。我正在程序运行时得到正确的答案,但如果我删除了行'printMatrix() ,我得到分段错误。 gdb日志如下

(gdb) backtrace
#0  __pthread_kill (threadid=0, signo=0)
    at ../nptl/sysdeps/unix/sysv/linux/pthread_kill.c:42
#1  0x0000000000400c85 in compute (args=0x7ffff74eede0) at tsp3.c:79
#2  0x00007ffff78be182 in start_thread (arg=0x7ffff64ed700)
    at pthread_create.c:312
#3  0x00007ffff75eaefd in clone ()
    at ../sysdeps/unix/sysv/linux/x86_64/clone.S:111
(gdb) 

为什么会发生这种情况。请解释。提前谢谢。

1 个答案:

答案 0 :(得分:0)

You are creating threads in compare function, and you pass compare as thread function, that's chaos. You maybe exceed available number of threads.