将数据写入PCIe设备时,可以使用写组合映射来暗示CPU,它应该向该设备生成64字节的TLP。
是否可以对读取执行类似的操作?是否以某种方式暗示CPU读取整个高速缓存行或更大的缓冲区,而不是一次读取一个字?
答案 0 :(得分:4)
英特尔拥有a white-paper on copying from video RAM to main memory;这应该相似但简单得多(因为数据适合2或4个向量寄存器)。
它表示NT加载会将整个数据缓存行从WC内存拉入LFB:
普通加载指令以与指令所请求大小相同的单位从USWC存储器中提取数据。相比之下,诸如MOVNTDQA之类的流加载指令通常会将完整的缓存数据行拉至CPU中的特殊“填充缓冲区”。随后的流负载将从该填充缓冲区读取,从而减少了很多延迟。
使用AVX2 _mm256_stream_load_si256()
或SSE4.1 / AVX1 128位版本。
填充缓冲区是有限的资源,因此,您绝对希望编译器生成asm,以将64字节高速缓存行的两个对齐的负载背对背加载,然后然后存储到常规内存中
如果一次要执行多个64字节块操作,请参阅英特尔白皮书,以获取有关使用小型弹跳缓冲区的建议,该缓冲区在L1d中保持高温,以避免在NT负载下将存储混入DRAM中。 (像NT存储区一样,对DRAM的L1d逐出也需要行填充缓冲区LFB)。
请注意,_mm256_stream_load_si256()
对于WC以外的其他存储器类型根本没有用。 NT提示在当前硬件上将被忽略,但是与常规负载相比,无论如何都会花费额外的ALU。有prefetchnta
,但那是完全不同的野兽。
答案 1 :(得分:1)
英特尔发布了有关如何进行64B PCIe传输的白皮书:How to Implement a 64B PCIe* Burst Transfer on Intel® Architecture。
原则是:
使用以下代码编写64B
_mm256_store_si256(pcie_memory_address, ymm0);
_mm256_store_si256(pcie_memory_address+32, ymm1);
_mm_mfence();
_mm256_store_si256
是(v)movdqa
的内在要素,而mfence
用于对商店进行更新并订购flush the WC buffer。
至于我对缓存子系统的WC部分的了解有限,有许多假设:
仅当WC缓冲区已满时,CPU才将WC缓冲区作为突发事务写入:
唯一保证由事务提供的WC传播到系统总线的元素 原子性。例如,对于P6系列处理器,一个完整的WC缓冲区将始终作为 使用任何块顺序的单个32位突发事务。在WC缓冲区逐出中,数据将作为部分被逐出, 同一块中包含的所有数据(对齐0 mod 8)将同时传播。
因此,必须确保使用一个空的WC缓冲区,否则将进行32B事务,甚至更糟的是,可能在较低的WC之前写入较高的数据块。
使用FPGA的practical experimentation on the Intel's forum有时会过早刷新WC缓冲区。
WC缓存类型可确保核心写入突发事务,但非核心也必须能够整体处理此事务。
特别是,在减法解码之后,根联合体必须能够将其作为64B事务处理。
从以上相同的论坛帖子中看来,uncore能够将连续的WC写合并到单个TLP中,但可以按照写顺序进行操作(例如,交换两个_mm256_store_si256
或为小于64B的大小留一个空洞)可能不属于根联合体功能。