假设我正在使用AVX2的VGATHERDPS - 这应该使用8个DWORD索引加载8个单精度浮点数.
当要加载的数据存在于不同的缓存行中时会发生什么?指令是作为硬件循环实现的,它逐个获取缓存行吗?或者,它是否可以立即向多个缓存行发出负载?
我读了几篇论述前者的文章(这是对我更有意义的文章),但我想更多地了解这一点.
链接到一篇论文:http://arxiv.org/pdf/1401.7494.pdf
以下是一些细节.
当一个进程调用时ibv_post_send(),在HCA的PCI接口上会发生什么?WQE是否封装在PCIe门铃内并通过Programmed IO写入?或者WQE是否由HCA单独读取?
当进程调用时会发生什么ibv_poll_cq()?HCA如何将CQE推送到系统内存?或者,如果它是基于拉力的,那么CPU如何在HCA中检测新的CQE?
我有两个数组:A用N_A随机整数和B使用N_B之间的随机整数0和(N_A - 1).我在以下循环中使用数字B作为索引A:
for(i = 0; i < N_B; i++) {
sum += A[B[i]];
}
Run Code Online (Sandbox Code Playgroud)
在Intel i7-3770(N_A= 2.56亿,N_B= 6400万)上进行试验,此循环仅需0.62秒,这相当于大约9纳秒的内存访问延迟.
由于这个延迟太小,我想知道硬件预取器是否正在发挥作用.有人可以提供解释吗?
为什么当我增加时,下面代码的运行时间会减少kNumCacheLines?
在每次迭代中,代码都会修改kNumCacheLines缓存行之一,使用clwb指令将该行写入 DIMM ,然后阻塞,直到存储到达内存控制器sfence。此示例需要 Intel Skylake-server 或更新的 Xeon 或 IceLake 客户端处理器。
#include <stdlib.h>
#include <stdint.h>
#define clwb(addr) \
asm volatile(".byte 0x66; xsaveopt %0" : "+m"(*(volatile char *)(addr)));
static constexpr size_t kNumCacheLines = 1;
int main() {
uint8_t *buf = new uint8_t[kNumCacheLines * 64];
size_t data = 0;
for (size_t i = 0; i < 10000000; i++) {
size_t buf_offset = (i % kNumCacheLines) * 64;
buf[buf_offset] = data++;
clwb(&buf[buf_offset]);
asm volatile("sfence" ::: …Run Code Online (Sandbox Code Playgroud) PCIe 3.0 x16和QPI 1.1(20通道)具有相同的有效带宽(16 GB/s).所以,我想大致了解两者之间的差异.
两者在延迟和消息速率(每秒数据包数量或TLP数量)方面有何不同?对于延迟,我的球场数量为QPI为20 ns,PCIe 3.0为200 ns.这些好估计?如果是,为什么PCIe的延迟要高得多 - 是否由于线路长度?
除了QPI提供缓存侦听这一事实之外,两者之间是否存在重大的架构差异?据我所知,两者都使用分层协议:通过物理层传输层.
为什么ASSERT_EQ下面会导致undefined reference to Bar::kBar错误?
编译: g++ a.cc -lgtest -lpthread
#include <gtest/gtest.h>
class Bar {
public:
static const size_t kBar = 0;
};
TEST(Basic, Basic) {
ASSERT_EQ(0, Bar::kBar);
}
int main(int argc, char **argv) {
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
Run Code Online (Sandbox Code Playgroud) c++ ×2
intel ×2
pci-e ×2
performance ×2
ram ×2
avx ×1
avx2 ×1
googletest ×1
hardware ×1
infiniband ×1
low-latency ×1
memory ×1
pci ×1
prefetch ×1
rdma ×1
simd ×1
x86 ×1