如何在 pthread_create() 函数中将矩阵作为参数传递?

Posted

技术标签:

【中文标题】如何在 pthread_create() 函数中将矩阵作为参数传递?【英文标题】:How to pass matrix as paramter in pthread_create() function? 【发布时间】:2021-11-20 01:03:56 【问题描述】:

我刚开始使用 OS 编程并正在探索线程。我想使用 pthread_create()、pthread_join() 和 pthread_exit() 函数将 2 个矩阵相乘并得到它们的乘积。但是,pthread_create() 将输入作为 void* 而我想传递一个 int** 参数。

我已经试过了:

    在 pthread_create() 函数中传递 m3 [我的结果矩阵],方法是将其类型转换为 (void*),然后在我的 threadMultiply 函数中将其类型转换回 (int**),但这不起作用 将 m1,m2,m3 作为全局变量,但这也给了我错误。

我很困惑,不知道如何解决这个问题。任何帮助将不胜感激,谢谢

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

int** alloc(int, int);
void display(int**, int, int);
void* threadMultiply(void* para);

int main()

    int r1,c1,r2,c2,r3,c3;  // rows and columns of each matrix
    int **m1, **m2, **m3;   // all 3 matrices

    // took inputs for r1,c1,r2,c2
    m1=alloc(r1,c1);
    printf("Enter the %d elements of the first matrix\n", r1*c1);
    for(int i=0;i<r1;i++)
        for(int j=0;j<c1;j++)
            scanf("%d", &m1[i][j]);
    m2=alloc(r2,c2);
    printf("Enter the %d elements of the second matrix\n", r2*c2);
    for(int i=0;i<r2;i++)
        for(int j=0;j<c2;j++)
                scanf("%d", &m2[i][j]);
    display(m1, r1, c1);
    display(m2, r2, c2);
        
    if(c1 != r2)
    
        printf("\nMatrices cannot be multiplied, check dimensions");
        return 0;
    
        
    r3 = r1;
    c3 = c2;
    m3=alloc(r3,c3);
    int MAX_THREADS = r3*c3;
    pthread_t threads[MAX_THREADS];
 
    // Creating threads. 
    for (int i = 0; i < MAX_THREADS; i++) 
    
        int *p;
        pthread_create(&threads[i], NULL, threadMultiply, (void*)(p));  //variable 'i' is of type int however function takes parameter of type void* so we have to do type-casting
    
     
    // joining and waiting for all threads to complete
    for (int i = 0; i < MAX_THREADS; i++)
        pthread_join(threads[i], NULL);   
        
        printf("\nThe resultant matrix is:");
        display(m3, r3, c3);
        
return 0;


int** alloc(int row, int col)

    //dynamic memory allocation for first 2 matrices
    int **m=0;
    m=(int**)malloc(row*sizeof(int*));

    for(int i=0;i<row;i++)
    
        *(m+i)=(int*)malloc(col*sizeof(int));
    
    
return m;


void *threadMultiply(void *para)

    int i,j,k;
    for(i=0;i<r1;i++)
    
        for(j=0;j<c2;j++)
        
            m3[i][j] == 0
                for(k=0;k<c1;k++)                  
                    m3[i][j]+=m1[i][k] * m2[k][j];
        
    
    printf("thread finished ...");
    pthread_exit(NULL);

编辑:

所以在阅读了 cmets 之后,我再次尝试了这个。代码编译但给我一个分段错误并且不显示第二个矩阵

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

typedef struct matrix   // using struct to reference 2 matrices in the threadMultiply function
    int r1, c1, r2, c2;
    int **m1;
    int **m2;
mat;

int** alloc(int, int);
void display(int**, int, int);
void accept(int**, int, int);
void* threadMultiply(void* para);

int main()

    int r1,c1,r2,c2,r3,c3;  // rows and columns of each matrix
    int **a, **b, **c;  // all 3 matrices
    long int *ret_value;    //using long int, since int cannot be type casted to void
    mat *m;
    printf("Enter the number of rows and columns(m x n) of the first matrix\n");
        printf("Rows=");
        scanf("%d", &r1);
        printf("Columns=");
        scanf("%d", &c1);
        a=alloc(r1,c1);
        printf("Enter the %d elements of the first matrix\n", r1*c1);
    accept(a,r1,c1);
        printf("Enter the number of rows and columns(m x n) of the second matrix\n");
        printf("Rows=");
        scanf("%d", &r2);
        printf("Columns=");
        scanf("%d", &c2);
        b=alloc(r2,c2);
        printf("Enter the %d elements of the second matrix\n", r2*c2);
    accept(b,r2,c2);
    printf("\nThe first matrix is:");
    display(a, r1, c1);
        printf("\nThe second matrix is:");
        display(b, r2, c2);
    
        if(c1 != r2)
        
            printf("\nMatrices cannot be multiplied, check dimensions");
            return 0;
        
        
        r3 = r1;
        c3 = c2;
        c=alloc(r3,c3);
        m->m1 = a;
    m->m2 = b;
    m->r1 = r1;
    m->c1 = c1;
    m->r2 = r2;
    m->c2 = c2;
    
    // Creating one thread for each operation
    int MAX_THREADS = r3*c3;    
    pthread_t threads[MAX_THREADS];
    for (int i = 0; i < MAX_THREADS; i++) 
    
        pthread_create(&threads[i], NULL, threadMultiply, (void*)(&m));  
    
     
    // joining and waiting for all threads to complete
    for(int i=0;i<MAX_THREADS;i++) 
    
        for(int j=0;j<r3;j++) 
        
            for(int k=0;k<c3;k++)
            
                //joining all the threads and retreiving value in ret_value
                if(pthread_join(threads[i],(void **) &ret_value) != 0)
                    perror("\nThread join failed.\n");
                c[j][k] += (long int)ret_value;   // int doesn't work here for some reason
            
        
    
        
        printf("\nThe resultant matrix is:");
        display(c, r3, c3);
        
return 0;


int** alloc(int row, int col)

    //dynamic memory allocation for first 2 matrices
    int **m=0;
    m=(int**)malloc(row*sizeof(int));

    for(int i=0;i<row;i++)
        *(m+i)=(int*)malloc(col*sizeof(int)); //m+i so that we can access all the rows by incrementing value of i. (m+i) = m[i]
    
return m;


void display(int **m, int r, int c)

    int i,j;
    for(i=0;i<r;i++)
    
        printf("\n[");
        for(j=0;j<c;j++)
        
            if(j<c-1)
            
                printf("%d\t", m[i][j]);
            
            else 
            
                printf("%d]", m[i][j]);
            

        
    


void accept(int **a, int row, int col)

    int i, j;
    printf("Enter the elements\n");

    for(i = 0; i < row; i++)
        for(j = 0; j < col; j++)
            scanf("%d", (*(a + i) + j));  //same as a[i][j]

void *threadMultiply(void *para)

    mat *m = (mat*)para;
    int i = m->r1;
    int j = m->r2;
    int k = m->c2;
    long int return_val = m->m1[i][k] * m->m2[k][j];
    printf("\nThread finished ...");
    pthread_exit((void *) return_val);

【问题讨论】:

此代码没有显示您尝试作为矩阵传递的内容,而是将一个无用的指针传递给p。您无需转换为 void *。您确实需要在线程函数中将para 转换为int ** 您的线程函数引用了m1m2m3,但它们未在该上下文中定义,因此不应编译。您也没有使用函数的参数或传递任何有意义的东西。请展示您的实际尝试之一,包括输入、预期输出和实际输出。 你将一个指向mat的指针传递给pthread_create。但是在线程函数中,您将para 转换为指向mat 的指针。指出不同? 注意:此注释属于编辑后的代码。 提示:阅读并尝试理解下面我的回答中的建议。 你声明mat *m(指向mat的指针),但从不为其分配存储空间。但是你下面的一些行取消引用m 【参考方案1】:

推荐:Pointer declaration (cppreference.com)

在这些部分中,

说明

指针用于间接寻址,这是一种普遍存在的编程技术;它们可用于实现按引用传递语义、访问具有动态存储持续时间的对象、实现“可选”类型(使用空指针值)、结构之间的聚合关系、回调(使用指向函数的指针)、通用接口(使用指向 void 的指针)等等。

指向无效的指针

指向任何类型对象的指针都可以隐式转换为指向 void 的指针(可选 const 或 volatile 限定),反之亦然:

...

指向 void 的指针用于传递未知类型的对象,这在泛型接口中很常见:malloc 返回 void*,qsort 期望用户提供的回调接受两个 const void* 参数。 pthread_create 需要用户提供的回调,该回调接受并返回 void*。在所有情况下,调用者都有责任在使用前将指针转换为正确的类型。


这如何应用于您的代码

在你的主要功能中:

// Creating threads. 
for (int i = 0; i < MAX_THREADS; i++) 
    int *p; // <- WARNING: pointer to int is uninitialized
    pthread_create(
        &threads[i], 
        NULL, 
        threadMultiply, 
        (void*)(p) // <- here you don't have to cast to void*
    );

指针p 未初始化。将要作为参数(参数)传递给线程启动函数的任何对象的地址分配给p

由于您只能传递一个参数,如果您的乘法函数需要三个矩阵(以及它们的行数和列数),就会出现问题。因此,您可以将信息打包到一个结构中。

示例

//global
struct arg 
    int r1, c1, r2, c2, r3, c3;
    int **m1;
    int **m2;
    int **m3;
;

int main()

    //...

    struct arg p = 
        r1, c1, 
        r2, c2, 
        r3, c3, 
        m1, m2, m3
    ; //for demonstration purposes only, 
       //normally you would have to allocate a struct for each thread

    pthread_create(&threads[i], NULL, threadMultiply, &p); //need address of operator

    //...


为了避免引入新的结构体,当然可以将所有变量声明为全局变量,但使用结构体可以(同时)将不同的参数传递给不同的线程。

然后是乘法函数:

void *threadMultiply(void *para)

    struct arg *p = para; //implicit cast
    int r1 = p->r1;
    int c1 = p->c1;
    //...
    int **m1 = p->m1;
    //...
    //do your multiplication

【讨论】:

非常感谢!我会试试这个,让你知道 我编辑了代码。现在给我分段错误

以上是关于如何在 pthread_create() 函数中将矩阵作为参数传递?的主要内容,如果未能解决你的问题,请参考以下文章

pthread_create,传两个参数,在函数里面怎么设置?

pthread_create() 函数详解

pthread_create如何传递两个参数以上的参数

多线程之pthread_create()函数

多线程之pthread_create()函数

如何在 LLVM 中获取函数指针