Проблема с передачей массива в struct при использовании pthread

#c #multithreading #pointers #struct #pthreads

#c #многопоточность #указатели #struct #pthreads

Вопрос:

 #include <math.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <pthread.h>

/* You may need to define struct here */
struct arg_type {
    int head;
    int length;
    int num;
    float *vec;
    double *sqsum;
};

/*!
 * brief subroutine function
 *
 * param arg, input arguments pointer
 * return void*, return pointer
 */
void *l2_norm(void *arg) { 
    /* TODO: Your code here */
    struct arg_type *a = (struct arg_type *)arg;
    a->sqsum[a->num] = 0.0f;
    for (int j = a->head; j < (a->head   a->length); j  ) {
        a->sqsum[a->num]  = a->vec[j] * a->vec[j];
    }
    pthread_exit(NULL);
}

/*!
 * brief wrapper function
 *
 * param vec, input vector array
 * param len, length of vector
 * param k, number of threads
 * return float, l2 norm
 */
float multi_thread_l2_norm(const float *vec, size_t len, int k) { 
    /* TODO: your code here */
    double sum = 0.0f;
    struct arg_type arg;
    pthread_t tid;
    
    *arg.vec = *vec;
    
    arg.length = (int)len / k;
    
    for (int i = 0; i < k; i  ) {
        arg.num = i;
        arg.head = arg.length * i;
        pthread_create(amp;tid, NULL, l2_norm, amp;arg);
    }
    
    pthread_join(tid, NULL);
    for (int j = 0; j < k; j  ) {
        sum  = arg.sqsum[j];
    }
    sum = sqrt(sum);
    return sum;
}
  

Я новичок и новичок в этой теме.

Это программа для вычисления нормы L2 с использованием нескольких потоков и сравнения времени с наивной реализацией.

После использования GDB я почти уверен, что программа застряла на строке 49.

*arg.vec = *vec;

Но я не уверен, почему и изо всех сил пытаюсь его отладить

Комментарии:

1. Приведенный выше код является частью кода, который имеет отношение к вопросу

Ответ №1:

arg.vec — это указатель, который не выделен, поэтому доступ к содержимому приведет к сбою.

Должно быть,

arg.vec = vec ;

Кроме того, другие проблемы в коде —

  1. Нужен массив аргументов: вы создали ‘k’ количество потоков, но вы передаете одну и ту же структуру ‘arg’ каждому потоку, поэтому переменные члены (т.Е. num, head) ‘arg’ могут быть одинаковыми внутри функций потока на основе параллельного запуска. Следовательно, вам нужен номер ‘k’ структуры ‘arg’, т.Е. Массив структуры arg и передача каждого его элемента в каждый поток.

  2. Нужен tid массива: кроме того, вы создали ‘k’ количество потоков, но вы присоединились только к одному потоку (т.Е. К последнему потоку), т. Е. Вы гарантируете, что будет завершен только последний поток. Чтобы гарантировать, что все потоки будут завершены, вам нужно дождаться создания всех потоков.

Комментарии:

1. Оказывается, нам все еще нужно изменить сигнатуру функции на float multi_thread_l2_norm (float *vec, size_t len, int k)

2. Поскольку элемент arg.vec в структуре вы объявили как непостоянный, поэтому присвоение его входящему vec (константа) выдаст ошибку. И поскольку вы не меняете содержимое vec в своей функции, so const было бы уместно.

Ответ №2:

Вы совместно используете переменную arg, где вы должны предоставить каждому потоку его копию

 // you need to allocate new memory zone before storing the vec in it
// ex : arg = malloc(sizeof(arg_type ));
*arg.vec = *vec;
  

в вашем случае весь поток будет иметь одинаковый arg.num, arg.head …