如何在 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 **
。
您的线程函数引用了m1
、m2
和m3
,但它们未在该上下文中定义,因此不应编译。您也没有使用函数的参数或传递任何有意义的东西。请展示您的实际尝试之一,包括输入、预期输出和实际输出。
你将一个指向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() 函数中将矩阵作为参数传递?的主要内容,如果未能解决你的问题,请参考以下文章