【问题标题】:Is a 128 bit int written or loaded in two instructions in C/C++?128 位 int 是否在 C/C++ 中的两条指令中写入或加载?
【发布时间】:2018-11-05 01:27:39
【问题描述】:

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

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

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

【问题讨论】:

  • 不能保证在所有实现上都定义该类型,编译器如何生成程序集取决于编译器、平台和编译标志/选项。这个问题没有可移植的答案。
  • Why isn't there int128_t?的可能重复
  • 我不会担心的。使用适当的同步技术,你应该没问题。
  • 不,你不知道这个,因为它在 C/C++ 中不存在。
  • 如果您担心竞争条件(读者会在作者写作时阅读),那么您这样做是正确的。防止竞争条件的工具取决于语言和操作系统,但一些常见的工具是互斥锁、临界区和信号。当您想确保自己是唯一做某事的人时,互斥锁非常有用。

标签: c++ c thread-safety int128


【解决方案1】:

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

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

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

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

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

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

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

【讨论】:

    【解决方案2】:

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

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

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

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

    【讨论】:

    • C++ 中没有int128_t
    • @SergeyA:好点子,虽然如果他们确实有这种类型,那么它需要是 128 位 2 的补码 signed
    • 我一直遇到这个问题,我需要写入这个值可能是执行时间的 0.1%。但是读取这个值的时间大约是执行时间的 10%。使用大多数线程同步是昂贵的。我希望找到解决这个成本的方法,但看起来它必须支付。谢谢
    • @MarcusKarpoff - 考虑使用装配总线锁之类的东西。这将比互斥锁快一个数量级,并且可能不会比管道转储贵。
    【解决方案3】:

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

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

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

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

    【讨论】:

    • 一些平台和 VIS 确实支持 128 位指针,至少在未来兼容。底层cpu是64位的。这解释了几乎所有主要编译器(intel、pgi、lahey 以不同的名称支持)中的存在
    猜你喜欢
    • 1970-01-01
    • 2012-03-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-01
    • 2015-12-22
    • 1970-01-01
    相关资源
    最近更新 更多