gpt4 book ai didi

c++ - 为单个线程强制执行语句的相对顺序

转载 作者:行者123 更新时间:2023-11-28 04:07:05 25 4
gpt4 key购买 nike

我想确保以下三个语句按照指定的确切顺序执行:

auto t1 = std::chrono::steady_clock::now(); // Statement 1
auto t2 = std::chrono::system_clock::now(); // Statement 2
auto t3 = std::chrono::steady_clock::now(); // Statement 3

编译器(或处理器)可以自由地重新排序这些语句,因为没有数据依赖性。参见 https://stackoverflow.com/a/38025837/1520427

C++11 添加了 std::atomic_signal_fence 以“按照顺序指示,在线程和在同一线程上执行的信号处理程序之间建立非原子和宽松原子访问的内存同步顺序线。”但是,根据 cppreference,“没有发出用于内存排序的 CPU 指令”,所以我不清楚这将如何阻止处理器重新排序。

我的问题:

以下代码是否足以阻止编译器对语句重新排序(假设所有代码都具有本地定义)?

auto t1 = std::chrono::steady_clock::now(); // Statement 1
std::atomic_signal_fence(std::memory_order::memory_order_release);
auto t2 = std::chrono::system_clock::now(); // Statement 2
std::atomic_signal_fence(std::memory_order::memory_order_release);
auto t3 = std::chrono::steady_clock::now(); // Statement 3
std::atomic_signal_fence(std::memory_order::memory_order_release);

处理器是否可以自由地重新安排这些操作的顺序?例如它可以执行他们 2-1-3 吗?如果是这样,std::atomic_thread_fence 会阻止它吗?

我是否需要引入人工数据依赖性(如链接问题中所示)以获得预期行为?

最佳答案

您不需要做任何事情来阻止编译时重新排序;非内联函数调用是可能通过全局变量相互交互的黑盒,因此编译器无法对它们重新排序。

或者如果 std::chrono::steady_clock::now(); 可以完全内联(可能使用内联汇编来读取时间戳),now() 的正确实现将使用类似 volatile 的东西访问,或 GNU C asm volatile以确保它不能与其他 now() 重新排序电话。 (更重要的是确保它不能 CSE 并被提升到循环之外,从而导致一切都花费零时间的错觉)。

与您链接的问题不同,您关心的排序不是简单的计算,例如 z = x + y; 它们是对通常是库函数的特殊函数调用。我没有检查规范,但如果计时函数有某种关于按顺序排序的规则,我不会感到惊讶。彼此。当然,高质量的实现会希望为您做到这一点。


Is the processor free to rearrange the order of these operations?

这是半可信的。在实际实现中不太可能,通常是 now()运行相当多的指令,大小与乱序执行窗口相当。 (例如,Skylake 上的 ROB 大小为 224 微指令。一个 rdtsc 本身就是 20 微指令,并且还有大量的缩放工作)。

OoO exec 通常是在最旧的就绪优先的基础上完成的,因此多次重复相同 now()函数不太可能乱序执行。

如果system_clocksteady_clock使用完全不同的 now , 和 now本身不做任何障碍,您可能希望使用特定于实现的机制来阻止 OoO exec。例如在 x86 上,_mm_lfence() .

例如如果system_clock开销低 now只是读取 volatile内存位置(在内核导出的页面中,由中断处理程序更新),但是 steady_clock::now使用 rdtsc , 重新排序是合理的。但没有可移植的方法来阻止它。


However, according to cppreference, "no CPU instructions for memory ordering are issued" so I'm unclear how this (atomic_signal_fence) would stop the processor from reordering things.

事实并非如此。这不是重点,也不是它的目的。乱序执行确保保留它按程序顺序运行的错觉(对于单个线程)。

因此atomic_signal_fence只需要确保 asm 程序顺序与在同一线程中运行的信号处理程序(或同一内核上的中断处理程序)的 C++ 抽象机源代码顺序相匹配,以观察该线程按程序顺序发生的操作。反之亦然,对于由信号处理程序完成的存储。

您是对的,您的尝试行不通。它可能只可能有助于允许编译时重新排序 now() 的(恕我直言)实现功能,然后可能只是作为 atomic_signal_fence() 的副作用可能被定义。例如就像 GNU C asm volatile("":::"memory") .虽然如果now()被打破并使用非 volatile asm 语句(因此多个 now() 调用可以相互 CSE),一个 asm volatile声明不会命令他们。

关于c++ - 为单个线程强制执行语句的相对顺序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58540495/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com