Как использовать пул потоков и очереди сообщений в многопоточном умножении матриц?

Я пытаюсь изучить многопоточность, выполняя многопоточную программу умножения матриц. Я вычисляю по одной строке за раз. Я сталкиваюсь с проблемой, когда использую меньше потоков, чем строк. Я прочитал много подобных сообщений, но не мог четко понять, как я могу их повторно использовать. Но есть два возможных метода.

  1. Использование пула потоков и создание очереди задач - после завершения задачи я не понял, как следующая задача назначается определенному потоку среди пула потоков.

  2. очереди сообщений.

Как использовать блокировку мьютекса для общей суммы переменных?

Пожалуйста, предложите мне возможные изменения, которые я должен добавить в следующую программу.

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

#define M 6
#define K 7
#define N 8
#define NUM_THREADS 4

int A[M][K] = { { 1, 4, 8, 4, 5, 6, 2 }, { 7, 3, 2, 4, 1, 4, 5 }, { 2, 3, 9, 4,
        7, 1, 5 }, { 4, 3, 9, 4, 7, 2, 5 }, { 1, 3, 9, 9, 7, 1, 3 }, { 2, 4, 9,
        3, 7, 1, 5 } };
int B[K][N] = { { 8, 3, 8, 4, 5, 6, 2, 3 }, { 1, 3, 2, 2, 3, 4, 8, 1 }, { 8, 3,
        9, 1, 7, 1, 5, 2 }, { 1, 3, 9, 2, 7, 2, 5, 2 },
        { 1, 3, 9, 2, 7, 1, 3, 3 }, { 2, 4, 9, 3, 7, 1, 5, 2 }, { 2, 4, 9, 3, 7,
                1, 5, 2 } };
int C[M][N];

struct v {
    int i; /* row */
    int j; /* column */
};

void *runner(void *param); /* the thread */

int main(int argc, char *argv[]) {

    int i, j, count = 0;
    for (i = 0; i < NUM_THREADS; i++) {

        //Assign a row and column for each thread
        struct v *data = (struct v *) malloc(sizeof(struct v));
        data->i = i;
        data->j = j;
        /* Now create the thread passing it data as a parameter */
        pthread_t tid[NUM_THREADS];       //Thread ID
        pthread_attr_t attr; //Set of thread attributes
        //Get the default attributes
        pthread_attr_init(&attr);
        //Create the thread
        pthread_create(&tid, &attr, runner, data);
        //Make sure the parent waits for all thread to complete
        pthread_join(tid, NULL );
        count++;

    }

    //Print out the resulting matrix
    for (i = 0; i < M; i++) {
        for (j = 0; j < N; j++) {
            printf("%d ", C[i][j]);
        }
        printf("\n");
    }
}

//The thread will begin control in this function
void *runner(void *param) {
    struct v *data = param; // the structure that holds our data
    int n, x, sum = 0; //the counter and sum

    //Calculating one row

    for (x = 0; x < N; x++) {
        for (n = 0; n < K; n++)

        {
            sum += A[data->i][n] * B[n][x];
        }
        //assign the sum to its coordinate
        C[data->i][data->j] = sum;
    }
    //Exit the thread
    pthread_exit(0); // How can I reuse this thread for another row instead of exiting it ?
}

Любая помощь будет оценена!


person Sys    schedule 10.08.2013    source источник


Ответы (2)


Как использовать блокировку мьютекса для общей переменной sum?

Вам нужно объявить mutex и использовать его для lock суммы перед суммой использования и unlock после суммы использования. Делайте это каждый раз, когда используете sum для его защиты.

Вот пример:

pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;

pthread_mutex_lock(&lock);

use sum ....

pthread_mutex_unlock(&lock);
person Lidong Guo    schedule 10.08.2013

Вы можете повторно использовать атрибут pthread для создания нескольких потоков. Также его необходимо уничтожить, чтобы освободить любые используемые ресурсы.

Также, чтобы потоки могли работать параллельно, сначала создайте их все, а затем затем присоедините к ним:

  ... 

  pthread_attr_t attr; //Set of thread attributes
  //Get the default attributes
  pthread_attr_init(&attr);
  pthread_t tids[NUM_THREADS] = {0};
  for (i = 0; i < NUM_THREADS; i++) {

    //Assign a row and column for each thread
    struct v *data = (struct v *) malloc(sizeof(struct v));
    data->i = i;
    data->j = j;

    //Create the thread
    pthread_create(&tids[i], &attr, runner, data);
    //Make sure the parent waits for all thread to complete
    count++;
  }
  pthread_attr_destroy(&attr);

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

  ...

И последнее замечание: в приведенных выше строках примеров проверка на наличие ошибок опущена. Но для любого «реального» кода всегда проверяйте результат системного вызова.

person alk    schedule 10.08.2013