【发布时间】:2018-08-01 21:53:54
【问题描述】:
我正在尝试验证不同英特尔 CPU 上 128 位操作的原子性,但由于某种原因,我的程序在我测试的每台机器上都未能通过原子性测试。我已经在 ivy bridge 和 Broadwell CPU 上进行了测试。我在下面包含了源代码。基本上它是同时增加两个 64 位计数器,它们组合在一起形成 128 位整数。如果原子性在 CPU 上起作用,那么低 64 位必须始终等于高 64 位。这就是这个程序正在测试的内容。但是测试总是失败,输出:
发现不一致 18550、18551
我正在运行 ubuntu 4.15,gcc 我将此代码编译为:
g++ -pthread -march=native test.cc -latomic
代码如下:
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
#include <unistd.h>
#include <thread>
__int128 __attribute__((__aligned__(16))) count;
void task() {
while(1) {
__int128 old_count, swapped_count;
do {
__atomic_load(&count, &old_count, __ATOMIC_SEQ_CST);
uint64_t old_lo = (uint64_t)old_count;
uint64_t old_hi = ((uint64_t)(old_count >> 64));
if (old_lo != old_hi) {
printf("Found inconsistency %lu, %lu\n", old_lo, old_hi);
exit(1);
}
__int128 __attribute__((__aligned__(16))) new_count;
new_count = old_hi + 1;
new_count <<= 64;
new_count |= (old_lo + 1);
swapped_count = __sync_val_compare_and_swap(&count, old_count, new_count);
uint64_t new_lo = (uint64_t)swapped_count;
uint64_t new_hi = (uint64_t)(swapped_count >> 64);
if (new_lo != new_hi) {
printf("Found inconsistency post swap %lu, %lu\n", new_lo, new_hi);
exit(1);
}
// At this point count must have changed one way or the other
if (count == old_count) {
printf("Count is still the same ????\n");
exit(1);
}
} while (old_count != swapped_count);
} // while (1)
}
int main() {
count = 0;
for (int i = 0; i < 2; i++)
new std::thread(task);
while(1)
sleep(1);
}
【问题讨论】:
-
你看到了什么?它是如何失败的?
-
我点击了那个 printf,它说“发现不一致”,即高 64 位与低 64 位不同。这表明这 128 位不是原子更新的。
-
on different intel CPUs哪些 CPU? -
Kamil,我确实提到了 Ivy 桥和 Broadwell。另外,我不认为它是另一个帖子的重复。