1

我知道 C 和 C++ 中存在一种int128_t类型。

如果我有两个线程,一个正在从包含这个 128 位整数的内存位置读取,另一个正在写入它。

这个值是否有可能被写为两个 64 位整数写入,还是一个 128 位整数写入?

4

3 回答 3

5

C 和 C++ 都不需要有int128_t类型,但如果编译器确实支持该类型,那么它必须signed2 的补码 128 位整数类型。但原子性不是必需的。

同时读取和写入任何非原子类型的行为是未定义的。

在 C++ 中,如果你可以使用std::atomic<int128_t>并且,如果你的平台确实有一个 atomic int128_t,那么这将只是一个typedef.

否则,在 C 语言中,您的编译器可能具有原子 128 位整数类型。如果没有,那么您可以使用内联汇编推出自己的版本。

于 2018-05-25T15:43:05.320 回答
5

在其他答案中讨论了支持。我将讨论实施问题。

通常在从内存读取时,编译器会发出处理器指令以将数据从内存中提取到寄存器中。这可能是原子的,具体取决于数据总线在处理器和内存之间的设置方式。

如果您的处理器支持 128 位传输并且内存支持 128 位数据总线,则这可能是一次读取(或写入)。

如果您的处理器支持 128 位 {register} 传输,但数据总线较小,则处理器将执行足够的取指以从内存中传输数据。这可能是原子的,也可能不是原子的,具体取决于您对原子的定义(它是一条处理器指令,但可能需要不止一次提取)。

对于不支持 128 位寄存器传输的处理器,编译器将发出足够的指令将内存读入寄存器。这是用于寄存器到内存或内存到寄存器传输。

对于内存到内存的传输(例如变量赋值),编译器可能会选择使用块读取和写入(如果您的处理器支持块读取和写入)。一些处理器支持 SIMD,其他处理器可能有块传输指令。例如,ARM 具有 LDM(加载多个)和 STM(存储多个)指令,用于从内存中加载多个寄存器并将多个寄存器存储到内存中。块读取和写入的另一种方法是使用 DMA 设备(如果存在)。DMA 可以在处理器执行其他指令时传输数据。但是,使用 DMA 的开销可能需要比使用 16 个 8 字节(字节)传输更多的指令。

总之,编译器不需要支持int128_t. 如果他们确实支持它,则有多种方法可以传输数据,具体取决于处理器和平台硬件支持。查看汇编语言以查看编译器发出的指令以支持int128_t.

于 2018-05-25T16:52:54.547 回答
3

首先,C++ 中没有 int128_t类型。最大的标准类型是int64_t.

其次,一些平台提供 128 位整数类型作为扩展。例如,gcc/clang/icc 支持__int128类型。

要在多线程场景中正确使用此类型,必须(与任何其他类型一样!)使用适当的同步构造来保护访问,或者使用std::atomic<__int128>. 支持的平台__int128,通常也支持它的原子版本。

为了满足您的好奇心,我不知道目前使用的任何通用硬件可以原生支持 128 位整数。

于 2018-05-25T15:47:05.307 回答