有没有更有效的方法可以原子地添加两个浮点数?
Are there any more efficient ways for atomically adding two floats?
我有一堆浮点数,它们由各种线程更新。数组的大小远大于线程数。因此,在特定浮标上同时访问的情况相当罕见。我需要C++03的解决方案。
以下代码以原子方式向其中一个浮点数添加一个值(实时演示)。假设它有效,这可能是最好的解决方案。 我能想到的唯一选择是将数组分成几束,并通过互斥锁保护每一束。但我不认为后者会更有效率。
我的问题如下。有没有原子添加浮点数的替代解决方案?谁能预测哪个是最有效的?是的,我愿意做一些基准测试。也许下面的解决方案可以通过放宽内存顺序限制来改进,即通过其他东西交换__ATOMIC_SEQ_CST
。我对此没有经验。
void atomic_add_float( float *x, float add )
{
int *ip_x= reinterpret_cast<int*>( x ); //1
int expected= __atomic_load_n( ip_x, __ATOMIC_SEQ_CST ); //2
int desired;
do {
float sum= *reinterpret_cast<float*>( &expected ) + add; //3
desired= *reinterpret_cast<int*>( &sum );
} while( ! __atomic_compare_exchange_n( ip_x, &expected, desired, //4
/* weak = */ true,
__ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST ) );
}
其工作原理如下。在//1
,x
的位模式被解释为int
,即我假设float
和int
具有相同的大小(32位)。在//2
,要增加的值以原子方式加载。在//3
,int
的位模式被解释为float
并添加总和。(请记住,expected
包含位于ip_x == x
的值。这不会更改ip_x == x
下的值。在//4
,求和的结果仅存储在ip_x == x
如果没有其他线程更改值,即如果expected == *ip_x
(doccu)。如果不是这种情况,则 do-loop 将继续,并且expected
包含找到的更新值 adip_x == x
。
GCC的原子访问函数(__atomic_load_n
和__atomic_compare_exchange_n
)可以很容易地被其他编译器的实现所交换。
有没有其他解决方案可以原子地添加浮点数?谁能预测哪个是最有效的?
当然,至少有几个浮现在脑海中:
-
使用同步原语,即自旋锁。会比比较交换慢一点。
-
事务扩展(参见维基百科)。会更快,但此解决方案可能会限制可移植性。
总体而言,您的解决方案非常合理:它速度很快,但可以在任何平台上工作。
在我看来,所需的内存顺序是:
__ATOMIC_ACQUIRE
-- 当我们读取__atomic_load_n()
中的值时__ATOMIC_RELEASE
-- 当__atomic_compare_exchange_n()
就是成功__ATOMIC_ACQUIRE
-- 当__atomic_compare_exchange_n()
失败时
为了使此函数更有效率,您可能希望将__ATOMIC_ACQUIRE
分别用于__atomic_load_n
和__ATOMIC_RELEASE
,__ATOMIC_RELAXED
用于__atomic_compare_exchange_n
success_memorder
和failure_memorder
。
在 x86-64 上,这不会更改生成的程序集,因为它的内存模型相对较强。与内存模型较弱的ARM不同。
- 在C++中,将大的无符号浮点数四舍五入为整数的最佳方法是什么
- 如何修复此错误:未定义对"距离(浮点数,浮点数,浮点数,浮点数,浮点数)"的引用
- C++浮点数据类型和字符串数据类型无法子到模板函数中
- 使用提升将数据从 PyObject 复制到浮点数 *
- 使用浮点数和双精度数的非常小数字的数学
- 使用英特尔内联函数将打包的 8 位整数乘以浮点数向量
- 如何在 c++ 中将小数点后两位数的浮点数分配给另一个浮点数
- 返回浮点数的小数位数
- txt 文件中浮点数的最大和最小值
- 为什么 std::cout 打印浮点数、双精度和长双精度到相同的小数精度?
- 将浮点数转换为无符号字符数组并打印出来
- 如何将时间字符串 (M:SS) 转换为浮点数
- 是否可以在 for 循环中添加两个浮点数?
- 有没有更有效的方法可以原子地添加两个浮点数?
- 添加 2 个浮点数时保持精度
- 如何在c++中将浮点数组添加到浮点向量中
- C++银行项目;如何将一组字符串读取为单独的浮点数并添加它们
- 添加浮点数、整数和指针
- 为了得到最精确的结果,应该按哪个顺序添加浮点数
- 使用std::accumulate以最佳精度添加浮点数