c++ - 连续内存块中的 C++ 原子操作
问题描述
std::atomic
在连续的内存块中分配值时,是否可以使用原子操作,可能使用库。
如果我有这个代码:
uint16_t* data = (uint16_t*) calloc(num_values, size);
我能做些什么来进行这样的原子操作:
data[i] = 5;
我将有多个线程同时分配给data
,可能在同一个索引处。这些线程在特定索引处修改值的顺序对我来说并不重要,只要修改是原子的,避免任何可能的数据损坏。
编辑:所以,根据@user4581301,我在这里为我的问题提供了一些背景信息。我正在编写一个程序来将深度视频数据帧与彩色视频数据帧对齐。用于深度和颜色的相机传感器具有不同的焦点特性,因此它们不会完全对齐。一般算法涉及将深度空间中的像素投影到颜色空间中的区域,然后用该单个像素覆盖深度帧中跨越该区域的所有值。我正在并行化这个算法。这些投影区域可能会重叠,因此当并行化时,对索引的写入可能会同时发生。
伪代码如下所示:
for x in depth_video_width:
for y in depth_video_height:
pixel = get_pixel(x, y)
x_min, x_max, y_min, y_max = project_depth_pixel(x, y)
// iterate over projected region
for x` in [x_min, x_max]:
for y` in [y_min, y_max]:
// possible concurrent modification here
data[x`, y`] = pixel
外部循环或最外面的两个循环是并行的。
解决方案
您将无法像这样完全按照您的意愿行事。
原子数组没有多大意义,也不是您想要的(您希望单个写入是原子的)。
你可以有一个原子数组:
#include <atomic>
#include <array>
int main()
{
std::array<std::atomic<uint16_t>, 5> data{};
data[1] = 5;
}
…但现在你不能只访问一个连续的uint16_t
s 块,这暗示着你想要这样做。
如果你不介意特定于平台的东西,你可以保留你的uint16_t
s 数组并确保你只对每一个使用原子操作(例如GCC 的__atomic
内在函数)。
但是,一般来说,我认为您会希望保持简单,并在访问普通数组时锁定互斥锁。测量以确保,但您可能会惊讶于您没有得到多少性能损失。
如果您急需原子,急需 的底层数组,急需uint16_t
标准解决方案,您可以等待 C++20 并为每个元素保留一个std::atomic_ref
(这就像非拥有),然后访问std::atomic
通过这些元素。但是,您仍然必须对任何直接访问元素的操作保持谨慎,可能通过使用锁,或者至少要非常小心在做什么和何时做什么。此时您的代码要复杂得多:确保它是值得的。
推荐阅读
- java - 测试时自动装配字段为空
- laravel - 使用 Larval 中间件将用户重定向到单独的域
- c# - C#中水平和垂直像素的大小不同?
- javascript - 从 getStaticProps 迭代对象并在组件模板中显示
- markov-chains - 马尔可夫切换
- mysql - 如何管理 Wordpress 应用程序以使 5000 个用户同时登录?
- linux - 将监视至少 2 个文件/目录中的更改并仅在两者都被修改时执行第三个脚本的脚本
- debugging - 使用 NVidia Nsight 实时捕获第一帧
- reactjs - 如果没有设置宽度/高度,React-image-crop 无法正确裁剪 .svg 图像
- oracle - 是否可以按每天/每周/每月的间隔插入约会日期