从x86 CPU生成64字节的读取PCIe TLP

时间:2018-08-19 14:44:44

标签: x86 pci-e

将数据写入PCIe设备时,可以使用写组合映射来暗示CPU,它应该向该设备生成64字节的TLP。

是否可以对读取执行类似的操作?是否以某种方式暗示CPU读取整个高速缓存行或更大的缓冲区,而不是一次读取一个字?

2 个答案:

答案 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

原则是:

  1. 将区域映射为 WC
  2. 使用以下代码编写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部分的了解有限,有许多假设:

  1. 仅当WC缓冲区已满时,CPU才将WC缓冲区作为突发事务写入:

      

    唯一保证由事务提供的WC传播到系统总线的元素   原子性。例如,对于P6系列处理器,一个完整的WC缓冲区将始终作为   使用任何块顺序的单个32位突发事务。在WC缓冲区逐出中,数据将作为部分被逐出,   同一块中包含的所有数据(对齐0 mod 8)将同时传播。

    因此,必须确保使用一个空的WC缓冲区,否则将进行32B事务,甚至更糟的是,可能在较低的WC之前写入较高的数据块。
    使用FPGA的practical experimentation on the Intel's forum有时会过早刷新WC缓冲区。

  2. WC缓存类型可确保核心写入突发事务,但非核心也必须能够整体处理此事务。
    特别是,在减法解码之后,根联合体必须能够将其作为64B事务处理。
    从以上相同的论坛帖子中看来,uncore能够将连续的WC写合并到单个TLP中,但可以按照写顺序进行操作(例如,交换两个_mm256_store_si256或为小于64B的大小留一个空洞)可能不属于根联合体功能。