有没有可能让两个变量自动递增。我有以下代码,因为它是一个多处理器、多线程的环境,缓存失效成为性能瓶颈。因此,我正在尝试最小化原子操作的数量。
__sync_add_and_fetch(&var1,1);
__sync_add_and_fetch(&var2,1);我看到第一个参数是一个指针,是否可以通过使用结构来实现我的情况?
附言:我不能使用锁。
发布于 2017-06-22 14:52:27
原子操作非常特殊,只提供有限的支持。将它们应用于两个变量对我来说是不可能的。
请注意,甚至不能保证原子操作是真正使用resp完成的。执行操作(即机器代码命令)。
走出了gcc的博士。5.47 Built-in functions for atomic memory access
并非所有目标处理器都支持所有操作。如果某个特定的操作无法在目标处理器上实现,则会生成一个警告,并生成一个调用外部函数的消息。外部函数将带有与内置函数相同的名称,并附加一个后缀'_n‘,其中n是数据类型的大小。
外部函数可能使用互斥锁来模拟原子操作。
但我猜,使用“肮脏的黑客”是可能的,而且只有一定的限制:
如果16位无符号计数器足够,您可以将其中两个放入一个32位变量中,其中c1c2 += 0x00000001递增一个,c1c2 += 0x00010000递增另一个,c1c2 += 0x00010001同时递增两个,或者使用原子操作:
/* combined counters c1 and c2 */
static uint32_t c1c2 = 0;
/* count c1 atomically */
__sync_fetch_and_add(&c1c2, 0x00000001);
/* count c2 atomically */
__sync_fetch_and_add(&c1c2, 0x00010000);
/* count c1 AND c2 atomically */
__sync_fetch_and_add(&c1c2, 0x00010001);这必须与适当的位移位和掩码相结合,以访问初始计数器值。
当然,计数器溢出可能是一个问题。这同样适用于64位平台上的两个32位计数器(考虑到原子操作通常仅适用于“机器字”宽度)。
顺便说一句。在谷歌搜索背景信息时,我偶然发现了这个:Why does __sync_add_and_fetch work for a 64 bit variable on a 32 bit system?。我发现原子操作可能需要充分的变量对齐才能正常工作(这一点值得一提的是)。
这可能是C11 Atomic Library为原子变量(例如atomic_uint_least32_t)提供专用类型的原因。
发布于 2020-04-14 20:10:56
除了两个奔腾处理器(类似于2001年的AMD处理器)之外,所有的奔腾处理器都支持128位原子操作。这是16个字节。
在C++中可以通过atomic<>模板实现对这些操作的支持,尽管最近的一个GCC版本对16字节值关闭了这一功能,并使用了锁。但是,各个编译器都有访问这些代码的方法,原则上也可以用机器语言编写。
操作的范围是有限的,但原则上您可以在常规C中做任何想做的事情,然后用CAS操作用新内容替换现有内容。CAS的意思就是: CPU,当且仅当B当前持有值C时,将值A写入内存位置B。因此:读取值;进行计算;然后使用CAS并在成功时使用CAS成功代码中断do..while循环。
https://stackoverflow.com/questions/44691392
复制相似问题