我正在尝试为英特尔的clwb指令找到不会使缓存行无效的配置或内存访问模式。我正在使用 NVDIMM 对 Intel Xeon Gold 5218 处理器进行测试。Linux 版本是 5.4.0-3-amd64。我尝试使用 Device?DAX 模式并直接将此字符设备映射到地址空间。我还尝试将此非易失性内存添加为新的 NUMA 节点,并使用numactl --membind命令将内存绑定到它。在这两种情况下,当我使用clwb缓存地址时,它都会被驱逐。我正在观察 PAPI 硬件计数器的驱逐,并禁用预取器。
这是我正在测试的一个简单循环。array 和 tmp 变量,都被声明为 volatile,所以加载是真正执行的。
for(int i=0; i < arr_size; i++){
tmp = array[i];
_mm_clwb(& array[i]);
_mm_mfence();
tmp = array[i];
}
Run Code Online (Sandbox Code Playgroud)
两次读取都会导致缓存未命中。
我想知道是否还有其他人试图检测是否有某种配置或内存访问模式会在缓存中留下缓存行?
经过认真的发展,CPU 获得了许多核心,在多个小芯片、numa 系统等上获得了分布式核心块,但数据仍然不仅必须通过 L1 缓存(如果在同一核心 SMT 上),而且还必须通过一些原子/互斥同步未经硬件加速的原始过程。
我想知道为什么英特尔或 IBM 没有想出这样的东西:
movcor 1 MX 5 <---- sends 5 to Messaging register of core 1
pipe 1 1 1 <---- pushes data=1 to pipe=1 of core=1 and core1 needs to pop it
bcast 1 <--- broadcasts 1 to all cores' pipe-0
Run Code Online (Sandbox Code Playgroud)
使其比其他方法快得多?GPU 支持块级快速同步点,例如barrier()或__syncthreads()。GPU 还支持本地阵列的并行原子更新加速。
当 CPU 增加 256 个核心时,此功能是否不会为在核心到核心带宽(和/或延迟)上遇到瓶颈的各种算法提供严重的扩展?
在用于x86硬件的C ++(使用平台上可用的任何低级内在函数)(例如Intel Skylake)中,是否可以将高速缓存行发送到另一个内核而无需强制该内核上的线程显式加载该行?
我的用例是在并发数据结构中。在这种情况下,在某些情况下,某个核心会在内存中经过某些地方,而这些地方可能在探寻斑点时由其他一些核心拥有。这些核心上的线程通常在条件变量中被阻塞,因此它们具有一些备用循环,可以在其中运行其他“有用的工作”。这里“有用的工作”的一个示例可能是它们将数据流式传输到另一个内核,该内核将在将来加载它们,因此加载内核不必在处理该行之前就等待该行进入其缓存。x86硬件上是否有一些可能的内在/指令可用?
__builtin_prefetch并不能很好地工作,因为出于某种原因,它最终将延迟添加回执行加载的代码中:(也许步幅配置不佳,但到目前为止我还没有取得很好的步幅。这可能会得到更好的处理,并且可以从确定最终会加载其行的其他内核确定地进行处理。
我问过一个类似的问题:较低级别的缓存是否可以具有更高的关联性并且仍然包含包含?
假设我们有 2 级缓存。(L1离CPU最近(内部/低级),L2在CPU之外,离主存最近)L1缓存可以写回吗?
我的尝试)
我认为我们只能通过缓存写入,而不能在 L1 中使用回写缓存。如果一个块在 L1 缓存中被替换,那么它必须被写回 L2 和主内存以保持包含。因此它必须被写透而不是写回。
所有这些疑问都来自以下考试问题。:P
问题)为了包含在多级缓存层次结构中的两个缓存级别 L1 和 L2 之间,以下哪些是必要的?
I) L1 必须是直写缓存
II) L2 必须是直写缓存
III) L2 的关联性必须大于 L1
IV) L2 缓存必须至少与 L1 缓存一样大A) 仅 IV
B)仅I 和 IV
C)仅I、II 和 IV
D) I、II、III 和 IV
根据我的理解,答案必须是选项(B)
我想将线程ping通到两个CPU插槽中的所有内核,并在线程之间写入通信而无需回写DRAM。
如果仅在一个插槽中使用内核,则写回高速缓存对我的吞吐量就可以了,但是对于两个插槽,我想知道是否有更快的速度,例如片上网络或Intel QuickPath Interconnect?
此外,是否有任何简单的方法可以利用这种功能而无需直接编写汇编代码?
参考:https : //software.intel.com/zh-cn/forums/intel-moderncode-for-parallel-architectures/topic/700477
TL;DR:在生产者-消费者队列中,放置一个不必要的(从 C++ 内存模型的角度来看)内存栅栏或不必要的强内存顺序是否有必要以牺牲可能更差的吞吐量为代价来获得更好的延迟?
C++ 内存模型是在硬件上执行的,方法是使用某种内存栅栏来实现更强的内存顺序,而不是将它们放在较弱的内存顺序上。
特别是,如果生产者这样做store(memory_order_release),而消费者使用 观察存储的值load(memory_order_acquire),则加载和存储之间没有围栏。在 x86 上根本没有栅栏,在 ARM 上栅栏是在存储之前和加载之后进行放置操作。
没有围栏存储的值最终会被没有围栏的负载观察到(可能在几次不成功的尝试之后)
我想知道在队列的两侧放置围栏是否可以更快地观察到值?如果有围栏和没有围栏,延迟是多少?
我希望只有一个循环load(memory_order_acquire)和pause/yield限制为数千次迭代是最好的选择,因为它无处不在,但想了解原因。
由于这个问题是关于硬件行为的,我希望没有通用的答案。如果是这样,我主要想知道 x86(x64 风格),其次是 ARM。
例子:
T queue[MAX_SIZE]
std::atomic<std::size_t> shared_producer_index;
void producer()
{
std::size_t private_producer_index = 0;
for(;;)
{
private_producer_index++; // Handling rollover and queue full omitted
/* fill data */;
shared_producer_index.store(
private_producer_index, std::memory_order_release);
// Maybe barrier here or stronger order above?
}
}
void consumer()
{
std::size_t private_consumer_index = 0;
for(;;)
{
std::size_t observed_producer_index = shared_producer_index.load( …Run Code Online (Sandbox Code Playgroud)