pthread编程中的共享数据

在pthread编程中我仍然不太确定。 如果有人能告诉我一个绝对的答案,我将不胜感激。

我之前的问题是: 如何在简单的Pthread编程中分配数组变量?

现在,我正在研究矩阵乘法。 它使用这个很好用:

typedef struct { int rowIdx; int (*matA)[SIZE], (*matB)[SIZE], (*matC)[SIZE]; } newType; int main (){ int matriksA[SIZE][SIZE]; int matriksB[SIZE][SIZE]; int matriksC[SIZE][SIZE]; for (i=0;i<NUM_THREAD;i++) { (*block).rowIdx = i; (*block).matA = matriksA; (*block).matB = matriksB; (*block).matC = matriksC; pthread_create(&arrThread[i], NULL, matrixMul, (void *)block); block++; } } void *matrixMul(void *x){ newType *p = (newType *) x; int i = (*p).rowIdx; int j,k; for (j=0;j<SIZE;j++){ int result = 0; for(k=0;k<SIZE;k++){ int MAik = (*p).matA[i][k]; int MBkj = (*p).matB[k][j]; result = result + (MAik*MBkj); } (*p).matC[i][j] = result; } pthread_exit(NULL); } 

matrixMul正在进行矩阵乘法matC = matA x matB。

我之前尝试过使用这个结构但它不起作用。

 typedef struct { int rowIdx; int **matA, **matB, **matC; } newType; 

显然,根据我的阅读,变量数组可以被视为一个指针,用于保存数组中第一个元素的地址。 至于二维数组,我们必须告诉编译器列的大小。 因此,我们必须在typedef结构中使用(* matA)[SIZE]而不是** matA。

但我仍然不确定我在那里做了什么。 我是否只是通过分配指针或者什么来将2D数组复制到另一个2D数组? 有点令人困惑….大声笑……

我的下一个问题是关于这些方面:

 (*block).matA = matriksA; (*block).matB = matriksB; (*block).matC = matriksC; 
  1. 那里到底发生了什么? 上面代码中的每个变量都有自己的矩阵数据副本吗? 或者他们只是通过让指针指向内存中的相同位置来共享它,这意味着matA,matB和matC的行为类似于静态变量(如面向对象编程)? 换句话说,是否只有matA,matB和matC的一个副本; 并且线程同时访问共享数据? 或者有很多’matA’副本,每个副本在RAM中有不同的分配?

  2. 与我的第一篇文章相同的问题,这些线背后发生了什么? (* z).arrA = arrayA; (* z).arrB = arrayB; (* z).arrC = arrayC;

  3. 以上代码是否足以完成任务(数组加法和矩阵乘法)? 或者从内存分配的角度来看,还有另一种更有效的方法吗?

@ Code-Guru:在那里我发布了新的问题。

线程编程的基本问题是确保两个单独的线程不可能同时修改数据,或者读取另一个线程可能正在修改的数据。 (如果没有数据可能被修改的危险,两个线程同时读取相同的非变化数据是完全可以的。)

应用于矩阵乘法问题,线程只会读取矩阵A和矩阵B,因此您不必控制对这些变量的访问 – 假设它们在启动线程之前已初始化。

另一方面,结果Matrix C将被访问以进行写入,因此您必须确保已对​​工作负载进行分区,以便没有两个线程可以访问相同的元素(它们正在处理Matrix的不相交子集) C),或者您必须协调访问,以便在给定时间只有一个线程正在修改给定的单元格,并且您已通过互斥( mutex )或等效的方式强制执行此操作。

你的问题

除了其他方面,您还没有展示如何定义block 。 如果你向我们展示一个SSCCE( 简短,自包含,正确的例子 ),就像我在下面给你看的那样,这会很有帮助。 它使我们不得不将代码片段反向工程为工作代码。 做得好,它不占用太多空间。 (这个答案的早期版本因为代码不完整而切断了!)

在原始文件中,您创建了NUM_THREAD线程来处理SIZE x SIZE矩阵。 由于您没有显示SIZENUM_THREAD的定义,我们必须假设两个大小相等。 根据两个常数的相对大小,可以使用各种不同的灾难配方。

  1. 线程都被赋予了相同的矩阵来处理,这正是你真正要问的。 每个线程都有一个指向同一内存的指针。

  2. 假设(*z).arrA = arrayA; 你指的是(*block).arrA = matriksA; 赋值,然后你将指向SIZE整数数组的指针分配给block->arrA (相当于(*block).arrA )。 这有点扭曲,但合法。 你需要小心使用它。

  3. 你问代码是否足够有效。 第一个子问题:它是否产生了正确答案(并且有保证)? 我还不确定。 但是,如果每个线程正在处理结果矩阵的一列,那应该足够安全。

SSCCE

此代码使用C99构造。 它不会在C89下编译。

 #include  #include  enum { SIZE = 3 }; typedef struct { int rowIdx; int (*matA)[SIZE]; int (*matB)[SIZE]; int (*matC)[SIZE]; } newType; extern void *matrixMul(void *); static void print_matrix(const char *tag, int d1, int d2, int matrix[d1][d2]) { printf("%s: (%dx %d)\n", tag, d1, d2); for (int i = 0; i < d1; i++) { printf("%d:", i); for (int j = 0; j < d2; j++) printf(" %6d", matrix[i][j]); putchar('\n'); } } int main(void) { int matriksA[SIZE][SIZE] = { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 } }; int matriksB[SIZE][SIZE] = { { 11, 12, 13 }, { 14, 15, 16 }, { 17, 18, 19 } }; int matriksC[SIZE][SIZE]; newType thedata[SIZE]; newType *block = thedata; pthread_t arrThread[SIZE]; for (int i = 0; i < SIZE; i++) { block->rowIdx = i; block->matA = matriksA; block->matB = matriksB; block->matC = matriksC; //matrixMul(block); pthread_create(&arrThread[i], NULL, matrixMul, block); block++; } for (int i = 0; i < SIZE; i++) pthread_join(arrThread[i], 0); print_matrix("Matrix A", SIZE, SIZE, matriksA); print_matrix("Matrix B", SIZE, SIZE, matriksB); print_matrix("Matrix C", SIZE, SIZE, matriksC); } void *matrixMul(void *x){ newType *p = (newType *) x; int i = p->rowIdx; for (int j = 0; j < SIZE; j++) { int result = 0; for(int k = 0; k < SIZE; k++) { int MAik = p->matA[i][k]; int MBkj = p->matB[k][j]; result += MAik * MBkj; } p->matC[i][j] = result; } //pthread_exit(NULL); return(0); } 

您可能会注意到我添加了矩阵打印function(并使用它)。 我还为一对3×3矩阵添加了样本数据,并且我已经validation答案是正确的。 我分两步完成了测试:

  1. 检查代码的单线程版本是否产生了正确的答案。
  2. 添加线程。

如果第1步产生错误的答案,你知道你只有基本的计算来修复; 它不是线程引发的问题(因为只有一个线程!)。 幸运的是,它产生了正确的答案。 添加线程非常简单。

产量

 $ ./ta Matrix A: (3 x 3) 0: 1 2 3 1: 4 5 6 2: 7 8 9 Matrix B: (3 x 3) 0: 11 12 13 1: 14 15 16 2: 17 18 19 Matrix C: (3 x 3) 0: 90 96 102 1: 216 231 246 2: 342 366 390 $