c - 锁定 C 中的分叉进程之间共享的内存
问题描述
在这个答案的基础上,我想制作一个程序,它可以自行在机器的 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]++;
}
我的问题如下:如果许多进程试图同时增加计数数组中的相同条目,我上面链接的答案是否安全?如果没有,有没有办法让进程一次使用一个数组,方法是要求它们在空闲时锁定它并在它不空闲时等待?
我尝试在网上搜索,但没有找到我要找的东西。我可能没有使用正确的关键字,因为我对并发编程不是很有经验。谢谢你的帮助!
解决方案
如果许多进程尝试同时增加计数数组中的相同条目,我链接到上面的答案是否安全?
不,这不安全。至少你会得到不正确的结果,其中一些增量可能会被“丢弃”(因为另一个进程在读取和写回增量值之间覆盖了该值)。请参阅“int num”的 num++ 是否是原子的?
如果没有,有没有办法让进程一次使用一个数组,方法是要求它们在空闲时锁定它并在它不空闲时等待?
好吧,您可以为数组设置一个信号量,或者为每个数组元素设置一个信号量,每个进程在访问之前尝试递减并在之后递增;甚至使用信号量本身作为计数器。(有关更一般的信息,请参阅Lock、mutex、semaphore...有什么区别?)但这很昂贵。更有效的方法是使用 C11 及更高版本中的原子特性对数组执行原子增量操作:
#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);
}
但就此而言,如果您需要做的只是计算每个输出值被看到的总次数,那么您可以避免所有这些。只需让每个进程保留自己的私有 count
数组,以记录每个输出在该进程中出现的次数,然后在最后将它们全部加在一起;毕竟,加法是关联的。您可以让每个工作进程通过管道或通过其自己独特的共享内存段或各种其他简单方式将其结果发送回父进程。
推荐阅读
- javascript - 在节点 js 上读取 .psv 文件内容花费的时间太长(超过 200 万行数据)
- javascript - 为什么 draft-js / react-rte 不会在文本编辑器中加载 iframe?
- sql-server - 在 SQL 中将一个长字符串拆分为一组较短的字符串
- netlogo - 如何更新用于在循环中选择海龟的比例?
- angular - Angular - 身份验证标头
- java - static 关键字在这里做什么?
- android - DiffUtil 违反 areContentTheSame 的合同 [下一个版本中的修复]
- c# - Xamarin 使用 AudioManager 形成 AdMob 问题
- visual-studio - 如何修复“命名空间microsoft.visualstudio中不存在类型或命名空间名称'xmleditor'(您是否缺少程序集引用?)”
- javascript - 关闭命令上下文时如何解决错误