c - 在 C 中使用多线程的矩阵乘法

标签 c matrix pthreads

我正在尝试使用 C 中的多个线程来实现矩阵乘法,我想让用户决定矩阵的大小。 我的代码:

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

void printAMatrix(int, int, int*);
void* rowMulti(void*);

int r1, c1;
int r2, c2;

int* mtx1;
int* mtx2;
int* res;
int* resM;

int main(int argc, char** argv) {
    printf("Input size of matrix 1:\n");
    scanf("%d %d", &r1, &c1);

    printf("Input size of matrix 2:\n");
    scanf("%d %d", &r2, &c2);

    if (c1 != r2) {
        printf("These two matrice cannot do matrix multiplication!\n");
        return -1;
    }

    mtx1 = (int*)calloc(r1 * c1, sizeof(int));
    mtx2 = (int*)calloc(r2 * c2, sizeof(int));

    int i, j, k;
    printf("Input matrix 1:\n");
    for (i=0; i< r1*c1; ++i) {
        scanf("%d", mtx1 + i);
    }

    printf("Input matrix 2:\n");
    for (i=0; i< r2*c2; ++i) {
        scanf("%d", mtx2 + i);
    }

    printf("Size of matrice:\n%d %d\n%d %d\n", r1, c1, r2, c2);
    printf("Matrix 1:\n");
    printAMatrix(r1, c1, mtx1);

    printf("Matrix 2:\n");
    printAMatrix(r2, c2, mtx2);

    res = (int*)calloc(r1*c2, sizeof(int));

    //Single thread
    for (i=0; i<r1; ++i) {
        for (j=0; j<c2; ++j) {
            int ele = 0;
            for (k=0; k<c1; ++k) {
                ele += *(mtx1 + c1*i+k) * *(mtx2 + c2*k+j);
            }
            *(res + c2*i + j) = ele;
        }
    }

    printf("Product of the 2 matrices:\n");
    printAMatrix(r1, c2, res);

    resM = (int*)calloc(r1*c2, sizeof(int));

    pthread_t* calThreads = (pthread_t*)calloc(r1, sizeof(pthread_t));

    for (i=0; i<r1; ++i) {
        if (pthread_create(calThreads+i, NULL, rowMulti, (void*)&i)) {
            perror("pthread_create: ");
            exit(1);
        }
    }

    for (i=0; i<r1; ++i) {
        if (pthread_join(*(calThreads+i), NULL)) {
            perror("pthread_join: ");
            exit(1);
        }
    }

    printf("Product of the 2 matrices(Para):\n");
    printAMatrix(r1, c2, resM);

    free(mtx1);
    free(mtx2);
    free(res);
    free(resM);
    free(calThreads);

    return 0;
}

void* rowMulti(void* rowNum) {
    int row = *(int*)rowNum;

    int j, k;

    for (j=0; j<c2; ++j) {
        int ele = 0;
        for (k=0; k<c1; ++k) {
            ele += *(mtx1 + c1 * row + k) * *(mtx2 + c2*k + j);
        }
        *(resM + c2*row + j) = ele;
    }
    printf("Row num: %d\n", row);
    pthread_exit(NULL);
}

void printAMatrix(int r, int c, int* mtx) {
    int i, j;   
    for (i=0; i<r; ++i) {
        for (j=0; j<c; ++j) {
            printf("%d ", mtx[c*i + j]);
        }
        printf("\n");
    }
    printf("\n");
}

例如,如果矩阵 1 有 4 行,则应生成 4 个线程; 0 应传递给线程 0 中的启动例程,1 应传递给线程 1 中的启动例程,依此类推。但是,线程的启动例程没有获得我期望的参数。 1 可能会传递到多个启动例程,然后我可能会在结果矩阵中丢失一行。一个例子:

Input size of matrix 1:
4 3
Input size of matrix 2:
3 5
Input matrix 1:
0 1 2 3 4 5 6 7 8 9 10 11
Input matrix 2:
8 7 6 5 4 3 2 1 0 1 2 3 4 5 6
Size of matrice:
4 3
3 5
Matrix 1:
0 1 2
3 4 5
6 7 8
9 10 11

Matrix 2:
8 7 6 5 4
3 2 1 0 1
2 3 4 5 6

Product of the 2 matrices:
7 8 9 10 13
46 44 42 40 46
85 80 75 70 79
124 116 108 100 112

Row num: 2
Row num: 1
Row num: 1
Row num: 3
Product of the 2 matrices(Para):
0 0 0 0 0
46 44 42 40 46
85 80 75 70 79
124 116 108 100 112

此处不计算第 0 行。有谁知道怎么解决吗?

最佳答案

我的想法是为第一个矩阵的每一行创建一个线程。

(线程同步,为了清晰和简单起见,跳过)

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

void printAMatrix(int, int, int*);


typedef struct{
    int row;            // thread row
    int mx2_r,mx2_c;    // size of second matrix;
    int *mtx1,          // first matrix
        *mtx2,          // second matrix
        *mtx3;          // results matrix
}THREAD_PARAM;



void ThreadCompute(pthread_t *thd, int r, int mx2_r,int mx2_c, int *mtx1, int *mtx2, int *mtx3);



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


    int r1, c1;
    int r2, c2;

    int* mtx1;
    int* mtx2;
    int* res;
    int* resM;


    int i, j, k;



    printf("Input size of matrix 1:\n");
    scanf("%d %d", &r1, &c1);

    printf("Input size of matrix 2:\n");
    scanf("%d %d", &r2, &c2);

    if (c1 != r2) {
        printf("These two matrice cannot do matrix multiplication!\n");
        return -1;
    }

    mtx1 = calloc(r1 * c1, sizeof(int));
    mtx2 = calloc(r2 * c2, sizeof(int));


    printf("Input matrix 1:\n");
    for (i=0; i< r1*c1; ++i) {
        scanf("%d", mtx1 + i);
    }

    printf("Input matrix 2:\n");
    for (i=0; i< r2*c2; ++i) {
        scanf("%d", mtx2 + i);
    }

    printf("Size of matrice:\n%d %d\n%d %d\n", r1, c1, r2, c2);
    printf("Matrix 1:\n");
    printAMatrix(r1, c1, mtx1);

    printf("Matrix 2:\n");
    printAMatrix(r2, c2, mtx2);

    res = calloc(r1*c2, sizeof(int));

    //Single thread
    for (i=0; i<r1; ++i) {
        for (j=0; j<c2; ++j) {
            int ele = 0;
            for (k=0; k<c1; ++k) {
                ele += *(mtx1 + c1*i+k) * *(mtx2 + c2*k+j);
            }
            *(res + c2*i + j) = ele;
        }
    }

    printf("Product of the 2 matrices:\n");
    printAMatrix(r1, c2, res);

    resM = calloc(r1*c2, sizeof(int));

    pthread_t* calThreads = calloc(r1, sizeof(pthread_t));

    for (i=0; i<r1; ++i) {
       ThreadCompute(calThreads+i, i, r2,c2,mtx1,mtx2,resM);
    }

    for (i=0; i<r1; ++i) {
        if (pthread_join(*(calThreads+i), NULL)) {
            perror("pthread_join: ");
            exit(1);
        }
    }

    printf("Product of the 2 matrices(Para):\n");
    printAMatrix(r1, c2, resM);

    free(mtx1);
    free(mtx2);
    free(res);
    free(resM);
    free(calThreads);

    return 0;
}



void *Thread_ThreadCompute(void *data){

    int i       = (( THREAD_PARAM* ) data)->row;
    int c1      = (( THREAD_PARAM* ) data)->mx2_r;
    int c2      = (( THREAD_PARAM* ) data)->mx2_c;
    int *mtx1   = (( THREAD_PARAM* ) data)->mtx1,
        *mtx2   = (( THREAD_PARAM* ) data)->mtx2,
        *res    = (( THREAD_PARAM* ) data)->mtx3;


    int j;
    int k;


    free(data);


    for (j=0; j<c2; ++j) {
        int ele = 0;
        for (k=0; k<c1; ++k) {
            ele += *(mtx1 + c1*i+k) * *(mtx2 + c2*k+j);
        }
        *(res + c2*i + j) = ele;
    }

    pthread_exit(NULL);

}

void ThreadCompute(pthread_t *thd, int r, int mx2_r,int mx2_c, int *mtx1, int *mtx2, int *mtx3){
    THREAD_PARAM *param=malloc(sizeof(THREAD_PARAM));
    param->row       = r;
    param->mx2_r     = mx2_r;
    param->mx2_c     = mx2_c;
    param->mtx1      = mtx1;
    param->mtx2      = mtx2;
    param->mtx3      = mtx3;

    if (pthread_create(thd, NULL, Thread_ThreadCompute, (void*)param)) {
        perror("pthread_create: ");
        exit(1);
    }
    return ;
}



void printAMatrix(int r, int c, int* mtx) {
    int i, j;   
    for (i=0; i<r; ++i) {
        for (j=0; j<c; ++j) {
            printf("%d ", mtx[c*i + j]);
        }
        printf("\n");
    }
    printf("\n");
}

关于c - 在 C 中使用多线程的矩阵乘法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34646215/

相关文章:

c - 在 C 中共享子项和父项之间的链表

c - 运行程序时出现错误#include <czmq.h>丢失

c - 如果(理论上)我应该被允许,为什么我不能打开文件进行阅读?

arrays - 每 2 列切片矩阵

C++ : fork/exec or pthread?

c - Perl XS 中的 OpenSSL 和线程

c - 如何发送带有填充字段的结构?

iOS 创建 UIButton 矩阵

c++ - 从类型 ‘Matrix&’ 的右值初始化类型 ‘Matrix’ 的非常量引用无效

c - 线程与互斥体同步