简体   繁体   English

多线程方式的矩阵乘法

[英]matrix multiplication in a multithreading way

Hi Im trying to teach myself multithreading by working the following exercise: multiply two hardcoded matrixes, matrix1 and matrix2, and save the result in matrix3.嗨,我尝试通过以下练习自学多线程:将两个硬编码矩阵相乘,matrix1 和 matrix2,并将结果保存在 matrix3 中。 The strategy is to assign one thread for the calculation of each element in the result matrix (matrix3).策略是分配一个线程来计算结果矩阵(matrix3)中的每个元素。

Though the program is runnable, but the result is not right.虽然程序是可以运行的,但是结果不对。 Any enlightenments why the result is wrong?任何启示为什么结果是错误的? Thanks!谢谢!

Code代码

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

#include "thread.h"

void *multiply(void *arguments);

#define X 2
#define Y 2
#define Z 3

int matrix1[X][Y] = {{0, 1}, {2, 3}};
int matrix2[Y][Z] = {{4, 5, 6}, {7, 8, 9}};
int matrix3[X][Z];

struct arguments_combo
{
    int rowIdxInMatrix1;
    int colIdxInMatrix2;
};

int main()
{
    thread_t threads[X * Z];

    for (int rowIdx = 0; rowIdx < X; rowIdx++)
    {
        for (int colIdx = 0; colIdx < Z; colIdx++)
        {
            struct arguments_combo arguments;
            arguments.rowIdxInMatrix1 = rowIdx;
            arguments.colIdxInMatrix2 = colIdx;
            pthread_create(&(threads[rowIdx * Z + colIdx]), NULL, multiply, (void *)&arguments);
        }
    }

    for (int rowIdx = 0; rowIdx < X; rowIdx++)
    {
        for (int colIdx = 0; colIdx < Z; colIdx++)
        {
            void *val_ptr;
            pthread_join(threads[rowIdx * Z + colIdx], &val_ptr);
            int *cur_val_ptr = (int *)val_ptr;
            printf("The rowIdx: %d and colIdx: %d and the val: %d\n", rowIdx, colIdx, *cur_val_ptr);
            matrix3[rowIdx][colIdx] = *cur_val_ptr;
            free(cur_val_ptr);
        }
    }

    return 0;
}

void *multiply(void *arguments)
{
    struct arguments_combo *data_ptr = (struct arguments_combo *)arguments;

    int rowIdxInMatrix1 = data_ptr->rowIdxInMatrix1;
    int colIdxInMatrix2 = data_ptr->colIdxInMatrix2;
    int *sum = malloc(sizeof(int));

    for (int i = 0; i < Y; i++)
    {
        *sum += matrix1[rowIdxInMatrix1][i] * matrix2[i][colIdxInMatrix2];
    }

    pthread_exit((void *)sum);
    return NULL;
}

Output输出

The rowIdx: 0 and colIdx: 0 and the val: 9
The rowIdx: 0 and colIdx: 1 and the val: 29
The rowIdx: 0 and colIdx: 2 and the val: 29
The rowIdx: 1 and colIdx: 0 and the val: 34
The rowIdx: 1 and colIdx: 1 and the val: 39
The rowIdx: 1 and colIdx: 2 and the val: 39

Well I am not an expert of this subject just tried to correct it.好吧,我不是这个主题的专家,只是试图纠正它。 Seems like the cause is this part似乎原因是这部分

struct arguments_combo arguments;
arguments.rowIdxInMatrix1 = rowIdx;
arguments.colIdxInMatrix2 = colIdx;
pthread_create(&(threads[rowIdx * Z + colIdx]), NULL, multiply, (void *)&arguments);

Could be wrong, but I think there is a race condition here.可能是错误的,但我认为这里存在竞争条件。 You gave this single arguments variable address to all thread, but you also overwrite it later on so when a thread accessing it likely having some other value already.您将这个单一arguments变量地址提供给所有线程,但稍后您也会覆盖它,因此当访问它的线程可能已经具有其他值时。

If you create an args array like this struct arguments_combo args[X * Z];如果你创建一个像这样的 args 数组struct arguments_combo args[X * Z]; at global scope and you change your code also to this:在全局范围内,您也将代码更改为:

args[rowIdx * Z + colIdx].rowIdxInMatrix1 = rowIdx;
args[rowIdx * Z + colIdx].colIdxInMatrix2 = colIdx;
pthread_create(&(threads[rowIdx * Z + colIdx]), NULL, multiply, (void *)&args[rowIdx * Z + colIdx]);

Then the result seems valid in this case那么在这种情况下结果似乎是有效的

The rowIdx: 0 and colIdx: 0 and the val: 7
The rowIdx: 0 and colIdx: 1 and the val: 8
The rowIdx: 0 and colIdx: 2 and the val: 9
The rowIdx: 1 and colIdx: 0 and the val: 29
The rowIdx: 1 and colIdx: 1 and the val: 34
The rowIdx: 1 and colIdx: 2 and the val: 39

Although sometimes it will give still random values.虽然有时它会给出仍然随机的值。 The reason is that you do not initialize *sum to 0 in multiply function so don't forget to do it also and than everything seems to be working fine.原因是您没有在multiply函数中将*sum初始化为0 ,所以不要忘记这样做,而且一切似乎都运行良好。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM