【问题标题】:Matrix multiplication with threads C使用线程 C 的矩阵乘法
【发布时间】:2019-03-12 16:34:40
【问题描述】:

我正在尝试使用多线程将给定矩阵相乘并将结果保存在全局矩阵中。代码如下:

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

struct mat_size {
    int row;
    int column;
};
struct mat_values {
    int * m_1;
    int * m_2;
    int i;
    int j;
};
int * result_matrix;
struct mat_size * result_size;
void * matrix_row_result(void * input) {
    struct mat_values *indicators = (struct mat_values *)input;
    int i = indicators->i;
    int j = indicators->j;
    int *m_1 = indicators->m_1;
    int *m_2 = indicators->m_2;

    int result = 0;
    int it = i;

    for(; it < result_size->column; it++)
    {
        printf("%d += %d * %d, ", result, *(m_1 + i * result_size->column + it), *(m_2 + it * result_size->column + j));
        result += *(m_1 + i*result_size->column + it) * *(m_2 + it*result_size->column + j);
    }
    putchar('\n');
    *(result_matrix + i * result_size->column + j) = result;
    // printf("%d ", *(result_matrix + i * result_size->column + j));
    pthread_exit(0);
}

void parallel_matrix_mult(int * m_1, int * m_2, int m, int n) {
    pthread_t * threads;

    result_size = (struct mat_size *)malloc(sizeof(struct mat_size));

    result_size->row = m;
    result_size->column = n;

    int number_threads = (result_size->row) * (result_size->column);
    printf("Creating %d threads and allocating %d size for final matrix\n", number_threads, number_threads * sizeof(int));
    result_matrix = calloc(m * n, sizeof(int));

    threads = (pthread_t *)calloc(number_threads, sizeof(pthread_t));
    int curr_thread = 0;
    for(size_t i = 0; i < result_size->row; i++) {
        for(size_t j = 0; j < result_size->column; j++) {
            printf("Allocating %d, %d to thread %d\n", i, j, curr_thread);
            struct mat_values *m_values = (struct mat_values *)malloc(sizeof(struct mat_values));
            m_values->m_1 = m_1;
            m_values->m_2 = m_2;
            m_values->i = i;
            m_values->j = j;
            int status = pthread_create((threads + curr_thread), NULL, matrix_row_result, m_values);
            printf("%d Status for thread %d\n", status, curr_thread);
            pthread_join(*(threads + curr_thread), 0);
            free(m_values);
            ++curr_thread;
        }
    }

    for(size_t i = 0; i < result_size->row; i++)
    {
        putchar('\n');
        for(size_t j = 0; j < result_size->column; j++)
        {
            printf("%d ", *(result_matrix + i * result_size->column + j));
        }

    }
    putchar('\n');
    free(result_size);
    free(result_matrix);
    free(threads);
}

int main() {
    int matrix_1[4][2] = {
        {1, 2},
        {3, 4},
        {5, 6},
        {7, 8}};
    int matrix_2[2][2] = {
        {1, 1},
        {1, 1}};
    int m = sizeof(matrix_1) / sizeof(matrix_1[0]);
    int n = sizeof(matrix_2[0]) / sizeof(int);
    printf("Rows: %d and Columns: %d\n", m, n);
    parallel_matrix_mult((int *)matrix_1, (int *)matrix_2, m,  n);
    return 0;
}

问题似乎是我缺乏对多线程的理解。我希望每个线程执行矩阵一的第 i 行和矩阵二的第 j 列之间的操作。不带线程的示例代码如下:

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

int main() {
    int matrix_1[4][2] = {
        {1, 2},
        {3, 4},
        {5, 6},
        {7, 8}
    };
    int matrix_2[2][2] = {
        {1, 1},
        {1, 1}
    };
    int * result_matrix;
    int * m = (int *) matrix_1;
    int * m2 = (int * ) matrix_2;

    result_matrix = (int * ) calloc(4 * 2, sizeof(int));
    for(size_t i = 0; i < 4; i++)
    {   
        putchar('\n');
        for(size_t j = 0; j < 2; j++)
        {
            for(size_t x = 0; x < 2; x++)
            {
                *(result_matrix + i * 2 + j) += *(m + i * 2 + x) * *(m2 + x * 2 + j);
            }
            printf("%d ", *(result_matrix + i * 2 + j));
        }
    }
    free(result_matrix);
}

现在的问题是,当我运行它输出的顺序代码时:

3 3 
7 7 
11 11 
15 15

正如预期的那样;另一方面,并​​发程序this是结果

3 3 
4 4 
0 0 
0 0

以下是我一直在使用的一些调试消息:

Rows: 4 and Columns: 2
Creating 8 threads and allocating 32 size for final matrix
Allocating 0, 0 to thread 0
0 Status for thread 0
0 += 1 * 1, 1 += 2 * 1, 
Allocating 0, 1 to thread 1
0 Status for thread 1
0 += 1 * 1, 1 += 2 * 1, 
Allocating 1, 0 to thread 2
0 Status for thread 2
0 += 4 * 1, 
Allocating 1, 1 to thread 3
0 Status for thread 3
0 += 4 * 1, 
Allocating 2, 0 to thread 4
0 Status for thread 4

Allocating 2, 1 to thread 5
0 Status for thread 5

Allocating 3, 0 to thread 6
0 Status for thread 6

Allocating 3, 1 to thread 7
0 Status for thread 7

【问题讨论】:

  • 你做pthread_create 紧跟pthread_join。这使得这一切都是串行的。使用两个循环:一个启动线程,第二个加入线程。
  • 谢谢我做出了改变@Someprogrammerdude

标签: c multithreading matrix


【解决方案1】:

对于您想要生成的每个结果,您需要 2 次乘法和 1 次加法。喜欢

result = matrix_1[3][0] * matrix_2[0][0] + matrix_1[3][1] * matrix_2[0][1];

但这不是你的代码正在做的事情。

看看这个:

int it = i;

for(; it < result_size->column; it++)
{
    printf("%d += %d * %d, ", result, *(m_1 + i * result_size->column + it), *(m_2 + it * result_size->column + j));
    result += *(m_1 + i*result_size->column + it) * *(m_2 + it*result_size->column + j);
}

result_size-&gt;column 的值始终为 2。但是,i 的值以及 it 的值跟随行号(即 0、1、2、3)。

所以只有前两个线程执行了两次循环。其他线程没有,因此结果是错误的。

这也可以从您的调试打印中看出:

0 Status for thread 0
0 += 1 * 1, 1 += 2 * 1,          // Two loops
Allocating 0, 1 to thread 1
0 Status for thread 1
0 += 1 * 1, 1 += 2 * 1,          // Two loops 
Allocating 1, 0 to thread 2
0 Status for thread 2
0 += 4 * 1,                      // One loops
Allocating 1, 1 to thread 3
0 Status for thread 3
0 += 4 * 1,                      // One loops 
Allocating 2, 0 to thread 4
0 Status for thread 4
                                 // No loops
Allocating 2, 1 to thread 5
0 Status for thread 5
                                 // No loops

所以你需要重新考虑你的算法。

顺便说一句:提示...首先让函数matrix_row_result 工作使用线程。然后当它以顺序模式工作时,您可以添加线程部分。换句话说 - 做“创建”,然后是“加入 - 像:

        int status = pthread_create((threads + curr_thread), NULL, matrix_row_result, m_values);
        pthread_join(*(threads + curr_thread), 0);

在调试功能时很好。当它起作用时,您将连接移出循环。

【讨论】:

  • 解决了!谢谢
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多