为什么我的矩阵乘法代码在c总是给垃圾值?(使用共享内存和fork)



这是我在c中做矩阵乘法实现fork和共享内存的代码。看起来我得到的值是最垃圾的值。也许我没有先初始化数组C的值它是结果数组。(我是C语言的初学者,这是我第一次使用共享内存)

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/shm.h>
#include <sys/ipc.h>
#include <sys/stat.h>
#include <sys/wait.h>
#define N 3
void doMulT(int row,int col,int x ,int a[][N],int b[][N],int c[]);
int main()
{
int Ma[N][N];
int Mb[N][N];
int segment_id;
pid_t pid=-1;
printf("Input the elements in Matrix A (%dx%d) : n",N,N);
for(int k = 0; k<N ;k++)
{
for(int d = 0; d<N ; d++)
{
scanf("%d",&Ma[k][d]);
}
}
printf("Input the elements in Matrix B (%dx%d) : n",N,N);
for(int k = 0; k<N ;k++)
{
for(int d = 0; d<N ; d++)
{
scanf("%d",&Mb[k][d]);
}
}
segment_id = shmget(IPC_PRIVATE,1024, S_IRUSR|S_IWUSR);
int *C = (int*)shmat(segment_id,NULL,0);
for(int i=0;i<N*N;i++)
{
if(pid != 0)
{
pid = fork();
}
}
if(pid == 0)
{
for(int i = 0; i<N; i++)
{
for(int j =0; i<N; j++)
{
if(C[i*N+j]==0)
{
doMulT(i,j,N,Ma,Mb,C);
}
}
}
}
else
{
for(int k =0;k<N*N;k++)
{
wait(NULL);
}
printf("==========Result==========n");
for(int i=0; i<N; i++)
{
for(int j=0; j<N; j++)
{
printf("%d",C[i*N+j]);
printf(" ");
}
printf("n");
}
}
shmdt(C);
shmctl(segment_id, IPC_RMID, NULL);
}
void doMulT(int row,int col,int x ,int a[][N],int b[][N],int c[])
{
for(int k=0; k<x; k++)
{
c[row*x+col]+=a[row][k]*b[k][col];
}
}

输入

示例
Input the elements in Matrix A (3x3) :
1 1 1
2 2 2
3 3 3
Input the elements in Matrix B (3x3) :
1 1 1
2 2 2
3 3 3

输出如

6 6 6
123482868 -745374 -2637821
456729394 -98475839 -2884829

这个回答的第一部分旨在说明原始程序中的问题和调试问题的方法。

我添加了一些printf输出,看看进程会做什么

if(pid == 0)
{
for(int i = 0; i<N; i++)
{
for(int j =0; i<N; j++)
{
if(C[i*N+j]==0)
{
printf("process %ld calculating (%d, %d)n", (long)getpid(), i, j);
doMulT(i,j,N,Ma,Mb,C);
}
}
}
}

并得到如下输出:

process 747 calculating (0, 204)                                                                                                                                                               
process 746 calculating (0, 292)                                                                                                                                                               
process 746 calculating (0, 293)                                                                                                                                                               
process 747 calculating (0, 205)                                                                                                                                                               
process 746 calculating (0, 294)                                                                                                                                                               
process 747 calculating (0, 206)                                                                                                                                                               
process 746 calculating (0, 295)                                                                                                                                                               
process 747 calculating (0, 207)                                                                                                                                                               

这意味着j的循环是错误的。

有一个错别字:

for(int j =0; i<N; j++)

必须

for(int j =0; j<N; j++) // j<N  instead of  i<N

另外我用memset将共享内存初始化为0.

修复循环后,我得到

process 238 calculating (0, 0)                                                                                                                                                              
process 238 calculating (0, 1)                                                                                                                                                              
process 238 calculating (0, 2)                                                                                                                                                              
process 238 calculating (1, 0)                                                                                                                                                              
process 238 calculating (1, 1)                                                                                                                                                              
process 238 calculating (1, 2)                                                                                                                                                              
process 238 calculating (2, 0)                                                                                                                                                              
process 238 calculating (2, 1)                                                                                                                                                              
process 238 calculating (2, 2)                                                                                                                                                              
==========Result==========                                                                                                                                                                  
6 6 6                                                                                                                                                                                       
12 12 12                                                                                                                                                                                    
18 18 18                                                                                                                                                                                    

这意味着在其他孩子开始活动之前,一个孩子完成了所有的工作。

处理循环中的延迟为其他进程获得一些工作留下了机会。

注意:这并不是一个真正的解决方案。主要目的是显示您不能依赖系统在过程之间分配工作。

它还表明,矩阵乘法不是多处理的好用例,因为矩阵单元的计算(至少对于您示例中的小矩阵)显然比创建新进程要快得多。

if(pid == 0)
{
for(int i = 0; i<N; i++)
{
for(int j =0; j<N; j++)
{
if(C[i*N+j]==0)
{
printf("process %ld calculating (%d, %d)n", (long)getpid(), i, j);
doMulT(i,j,N,Ma,Mb,C);
sleep(1); // give other processes a chance to do some work
}
}
}
}

对于一个好的解决方案,您必须实现一种为每个子进程分配特定任务的方法。一种选择是将循环变量i(或者可能为行和列传递两个单独的循环变量)传递给子进程中的处理函数,如下面的版本所示。

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/shm.h>
#include <sys/ipc.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <memory.h>
#include <errno.h>
#include <stdlib.h>
#define N 3
#define SIZE 1024
void doMulT(int row,int col,int x ,int a[][N],int b[][N],int c[]);
int main()
{
int Ma[N][N] = {
{1, 1, 1},
{2, 2, 2},
{3, 3, 3}
};
int Mb[N][N] = {
{1, 1, 1},
{2, 2, 2},
{3, 3, 3}
};
int segment_id;
pid_t pid=-1;
#if 0
printf("Input the elements in Matrix A (%dx%d) : n",N,N);
for(int k = 0; k<N ;k++)
{
for(int d = 0; d<N ; d++)
{
scanf("%d",&Ma[k][d]);
}
}
printf("Input the elements in Matrix B (%dx%d) : n",N,N);
for(int k = 0; k<N ;k++)
{
for(int d = 0; d<N ; d++)
{
scanf("%d",&Mb[k][d]);
}
}
#endif
segment_id = shmget(IPC_PRIVATE, SIZE, S_IRUSR|S_IWUSR);
int *C = (int*)shmat(segment_id,NULL,0);
memset(C, 0, SIZE);

for(int i=0; (pid != 0) && (i<N); i++)
{
for(int j=0; (pid != 0) && (j<N); j++)
{
if(pid != 0)
{
pid = fork();
if(pid == 0)
{
printf("process %ld calculating (%d, %d)n", (long)getpid(), i, j);
doMulT(i,j,N,Ma,Mb,C);
exit(0);
}
}
}
}

if(pid != 0)
{
while(wait(NULL) != -1 || (errno != ECHILD))
{
;
}
printf("==========Result==========n");
for(int i=0; i<N; i++)
{
for(int j=0; j<N; j++)
{
printf("%d",C[i*N+j]);
printf(" ");
}
printf("n");
}
}
shmdt(C);
shmctl(segment_id, IPC_RMID, NULL);
}
void doMulT(int row,int col,int x ,int a[][N],int b[][N],int c[])
{
for(int k=0; k<x; k++)
{
c[row*x+col]+=a[row][k]*b[k][col];
}
}

输出如下所示:

process 7489 calculating (0, 0)                                                                                                                                                             
process 7495 calculating (2, 0)                                                                                                                                                             
process 7496 calculating (2, 1)                                                                                                                                                             
process 7497 calculating (2, 2)                                                                                                                                                             
process 7493 calculating (1, 1)                                                                                                                                                             
process 7490 calculating (0, 1)                                                                                                                                                             
process 7494 calculating (1, 2)                                                                                                                                                             
process 7492 calculating (1, 0)                                                                                                                                                             
process 7491 calculating (0, 2)                                                                                                                                                             
==========Result==========                                                                                                                                                                  
6 6 6                                                                                                                                                                                       
12 12 12                                                                                                                                                                                    
18 18 18                                                                                                                                                                                    

最新更新