pthread_join зависает соответственно случайному значению глобальной переменной - PullRequest
0 голосов
/ 29 октября 2019

Я создал этот код, используя pthreads. Цель состоит в том, чтобы создать массив X[N][D] и присвоить ему случайные значения. Вы можете прочитать элементы этого массива как коэффициенты некоторых точек.

На следующем шаге я пытаюсь вычислить массив distances[N], который содержит все расстояния между последним элементом (N th) и каждым другим элементом. Расчет расстояний выполняется с использованием pthreads.

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <math.h>

#define N 10
#define D 2         //works for any d
#define NUM_THREADS 8


//double *distances;
//int global_index = 0;
pthread_mutex_t lock;
double *X;

typedef struct
{
    //int thread_id;
    double *distances;
    int *global_index ;
    pthread_mutex_t lock;
    double *X;

}parms;

void *threadDistance(void *arg)
{
    parms *data = (parms *) arg;
    double *distances = data->distances;
    double *X = data->X;
    int *global_idx = data -> global_index;

    int idx,j;
    //long id = (long)arg;
    pthread_mutex_lock(&lock);

    while(*global_idx<N)
    {
        //printf("Thread #%ld , is calculating\n", id);
        idx = *(global_idx);
        (*global_idx)++;
        pthread_mutex_unlock(&lock);
        for(j=0 ; j<D; j++)
        {
            distances[idx] = pow(X[(j+1)*N-1]-X[j*N+idx], 2);
            //printf("dis[%d]= ", dis);
            //printf("%f\n",distances[idx]);
        }
        //printf("global : %d\n", *global_idx);
    }


    pthread_exit(NULL);


}

void calcDistance(double * X, int n, int d)
{
    int i;
    int temp=0;
    pthread_t threads[NUM_THREADS];
    double *distances = malloc(n * sizeof(double));

    parms arg;
    arg.X = X;
    arg.distances = distances;
    arg.global_index = &temp;

    for (i=0 ; i<NUM_THREADS ; i++)
    {
        pthread_create(&threads[i], NULL, threadDistance, (void *) &arg);
    }

    for(i = 0 ; i<NUM_THREADS; i++)
    {
        pthread_join(threads[i], NULL);
    }

    /*----print dstances[] array-------*/
    printf("--------\n");
    for(int i = 0; i<N; i++)
    {
        printf("%f\n", distances[i]);
    }
    /*------------*/
    free(distances);
}

int main()
{

    srand(time(NULL));

    //allocate the proper space for X
    X = malloc(D*N*(sizeof(double)));

    //fill X with numbers in space (0,1)
    for(int i = 0 ; i<N ; i++)
    {
        for(int j=0; j<D; j++)
        {
            X[i+j*N] = (double) (rand()  / (RAND_MAX + 2.0));
        }

    }

    calcDistance(X, N, D);


    return 0;
}

Проблема заключается в том, что код выполняется полностью только при N=100000. Если N!=100000 код просто зависает, и я обнаружил, что источником проблемы является функция pthread_join(). Во-первых, я не могу понять, почему зависание зависит от значения N.

Во-вторых, я попытался printf() указать значение global_index (как вы можете видеть, это закомментировано в этомконкретный образец кода). Как только я раскомментирую команду printf("global : %d\n", *global_idx);, программа перестает зависать, независимо от значения N.

Мне кажется сумасшедшим, так как различия между подвешиванием и не подвешиванием настолько не имеют значения.

1 Ответ

1 голос
/ 30 октября 2019

относительно:

pthread_mutex_lock(&lock); 
while(*global_idx<N) 
{  
    // ... 
    pthread_mutex_unlock(&lock); 

В результате после первой итерации цикла мьютекс всегда разблокируется. Предложите переместить вызов на pthread_mutex_lock() внутрь вершины цикла.

после внесения вышеуказанных исправлений, я затем установил N на 10000. Затем перекомпилировал и т. Д. В результате возникла ошибка сегмента. событие, поэтому неправильная обработка мьютекса - не единственная проблема.

в отношении:

* First of all I cannot understand why the hang depends on the value of N.*

кажется, что программа фактически завершается с ошибкой сегмента, а не зависает

...