【问题标题】:Lock memory shared between forked processes in C锁定 C 中的分叉进程之间共享的内存
【发布时间】:2021-04-19 13:11:33
【问题描述】:

this answer 的基础上构建,我想创建一个程序,它可以自行在机器的 CPU 上分配大量独立计算。计算输出集合 {0, ..., n - 1} 中的一个数字。我的目标只是计算大小为 n 的数组中每个输出的出现次数。

为了清楚起见,下面是每个子进程中的主循环的样子:

for (i = start_range_for_this_process; i < end_range_for_this_process; i++)
{
    input = generate_input(i);
    output = the_computation(input);
    count[output]++;
}

我的问题如下:如果许多进程试图同时增加计数数组中的相同条目,我上面链接的答案是否安全?如果没有,有没有办法让进程一次使用一个数组,方法是要求它们在空闲时锁定它并在它不空闲时等待?

我尝试在网络上搜索,但没有找到我要查找的内容。我可能没有使用正确的关键字,因为我对并发编程不是很有经验。感谢您的帮助!

【问题讨论】:

    标签: c concurrency locking fork shared-memory


    【解决方案1】:

    如果许多进程尝试同时增加计数数组中的相同条目,我上面链接的答案是否安全?

    不,这不安全。至少你会得到不正确的结果,其中一些增量可能会被“丢弃”(因为另一个进程在读取值和写回增量值之间覆盖了该值)。见Can num++ be atomic for 'int num'?

    如果没有,有没有办法让进程一次使用一个数组,方法是要求它们在空闲时锁定它并在它不空闲时等待?

    好吧,您可以为数组设置一个semaphore,或者为每个数组元素设置一个semaphore,每个进程在访问之前尝试递减并在之后递增;甚至使用信号量本身作为计数器。 (有关更多一般信息,请参阅Lock, mutex, semaphore... what's the difference?。)但这很昂贵。更有效的方法是在 C11 及更高版本中使用 atomic features 对数组执行原子增量操作:

    #include <stdatomic.h>
    ...
    atomic_int *count = attach_shared_memory();
    for (i = start_range_for_this_process; i < end_range_for_this_process; i++)
    {
        input = generate_input(i);
        output = the_computation(input);
        atomic_fetch_add_explicit(&count[output], 1, memory_order_relaxed);
    }
    

    但就此而言,如果您需要做的只是计算每个输出值被看到的总次数,那么您可以避免所有这些。只需让每个进程保留其自己的 private count 数组,以了解每个输出在 this 进程中出现的次数,然后在最后将它们全部加起来;毕竟,加法是关联的。您可以让每个工作进程通过管道、或通过其自己独特的共享内存段或其他各种简单方式将其结果发送回父进程。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-31
      • 1970-01-01
      • 1970-01-01
      • 2013-11-24
      • 2012-07-03
      • 2018-03-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多