【问题标题】:Problems with C forks, wrong results, probably shared memoryC fork 的问题,错误的结果,可能是共享内存
【发布时间】:2015-12-27 19:04:09
【问题描述】:

我有一个任务是使用共享内存使用叉子进行矩阵乘法,然后将时间结果与没有叉子的乘法进行比较,所以这里是没有它们的乘法:

int matrizA[Am][An];
int matrizB[An][Bp];

//here i fill the matrix from a .txt file

int matrizR[Am][Bp];
int a,b,c;
for (a=0; a < Am; a++){
    for (b = 0; b < Bp; b++)
    {
        matrizR[a][b] = 0;
        for (c=0; c<An; c++){
            matrizR[a][b] += matrizA[a][c] * matrizB[c][b]; 
        }
    }
}

然后我尝试实现fork,但结果错误,我不确定我是否必须实现共享内存以及matrizA、matrizB和matrizR2应该在哪里共享?我是怎么做到的?

int matrizR2[Am][Bp];
pid_t pids[Am][Bp];
int h,j;

/* Start children. */TY
for (h = 0; h < Am; ++h) {
    for (j=0; j<Bp ; ++j){
      if ((pids[h][j] = fork()) < 0) {
        perror("fork");
        abort();
      } else if (pids[h][j] == 0) {
        matrizR2[h][j] = 0;
        for (c=0; c<An; c++){
            matrizR2[h][j] += matrizA[h][c] * matrizB[c][j]; 
        }
        printf("im fork %d,%d\n",h,j);
        exit(0);
      }
    }
}
/* Wait for children to exit. */
int status;
pid_t pid;
while (n > 0) {
  pid = wait(&status);
  --n; 
}

【问题讨论】:

  • 当你fork一个新进程时,实际上是创建了一个新的进程,任何进程的内存都与任何其他进程是分开的。所以是的,你需要共享内存,或者你可以使用 threads 来代替。
  • 在这个例子中如何实现共享内存?我读了这个,但真的不明白它必须link
  • @Stas 就像那个例子一样,我的 glob_var 应该是所有矩阵?我如何初始化它们?
  • 必须使用进程和共享内存是否是要求?否则线程会容易得多。

标签: c fork shared-memory


【解决方案1】:

没有给出完整的解决方案,因为这是一个家庭作业,但您用于在 Unix 上获取共享内存的函数记录在这里:http://pubs.opengroup.org/onlinepubs/009695399/functions/shmget.html

您可以调用shmget(),然后在每个子进程中将提供给您的标识符传递给shmat(),以获取指向共享内存的指针。

另一种方法是让每个进程在管道中传回其结果并复制它们,但这会慢得多。另一种是使用线程而不是进程,因为线程共享内存。另一个是传递消息。另一个是内存映射文件。但是,将共享内存强制转换为指向结构的指针是最简单的方法,并且具有最佳性能。

最后,如果要写入同一个共享内存,需要注意不要让两个进程写入同一个内存。如果您每行打开一个进程,并且您的行正确对齐,则应该没有问题,但安全的方法是使用锁或原子变量。

【讨论】:

  • 你确定使用管道会比共享内存慢很多吗?想象每个子进程处理一行,二进制将其写入管道(每个子进程一个管道),父进程只是整理它从管道中读取的内容。它应该更难写,但不确定时间。但我很确定它会比在每个变量写入时使用共享内存和全局锁更快(无论如何都赞成:-))。
  • 但正如@lorehead 所说,我不应该使用锁,因为每个进程都会写入数组的不同部分,所以永远不会有两个进程写入同一个内存空间,我对吗?
  • 原子变量不应该在每次写入时都需要全局锁。事实上,如果阵列中没有进程的部分与任何其他进程共享高速缓存行,则所有进程都应该能够写入它们的部分而根本没有开销。我想,您也可以为每个对象使用不同的共享内存块。但是要回答您的问题:考虑必须制作多少个数组的每个副本才能通过管道传输它们。
  • 这是一种避免处理任何原子内容的hackish解决方案:将行声明为指向行向量的指针数组,然后将每个行初始化为只有一个子进程的共享内存段将打开。在现实世界中,这不是一个很好的解决方案,因为您没有缓存一致性和大量开销,但它以透明的方式使每个人接触的内存块完全分开。
猜你喜欢
  • 2015-07-20
  • 1970-01-01
  • 2011-02-10
  • 2012-04-26
  • 2021-01-19
  • 2010-12-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多