【问题标题】:how to use movntdqa to avoid cache pollution?如何使用movntdqa避免缓存污染?
【发布时间】:2010-10-25 11:26:06
【问题描述】:

我正在尝试编写一个不会将源内存加载到 cpu 缓存的 memcpy 函数。目的是避免缓存污染。 下面的 memcpy 函数可以工作,但会像标准 memcpy 一样污染缓存。我正在使用 P8700 proccesoor 和 Visual C++ 2008 express。我看到了英特尔 vtune 的 cpu 缓存使用情况。

void memcpy(char *dst,char*src,unsigned size){
    char *dst_end=dst+size;
    while(dst!=dst_end){
        __m128i res = _mm_stream_load_si128((__m128i *)src);
        *((__m128i *)dst)=res;
        src+=16;
        dst+=16;
    }
}

我有另一个版本,具有相同的结果 - 工作但会污染缓存。

void memcpy(char *dst,char*src,unsigned size){

        char *dst_end = dst+size;

        __asm{
        mov edi, dst 
        mov edx, dst_end 
        mov esi,src
        inner_start: 
        LFENCE 
      MOVNTDQA xmm0,    [esi ]
      MOVNTDQA xmm1, [esi+16] 
      MOVNTDQA xmm2, [esi+32] 
      MOVNTDQA xmm3, [esi+48] 
      //19. ; Copy data to buffer 
      MOVDQA [edi], xmm0 
      MOVDQA  [edi+16], xmm1 
      MOVDQA  [edi+32], xmm2 
      MOVDQA  [edi+48], xmm3 
    //  25. ; Increment pointers by cache line size and test for end of loop 
      add esi, 040h 
      add edi, 040h 
      cmp edi, edx 
      jne inner_start 


}
}

更新:这是测试程序

        void test(int table_size,int num_iter,int item_size){
            char *src_table=alloc_aligned(table_size*item_size);//return value is aligned on 64 bytes
            char *dst=alloc_aligned(item_size); //destination is always the same buffer
            for (int i=0;i<num_iter;i++){
                int location=my_rand()%table_size;
                char *src=src_table+location*item_size;//selecting a different src every time
                memcpy(dst,src,item_size);
            }

        }
main(){
       test(1024*32,1024*1024,1024*32)
}

【问题讨论】:

  • 请注意,如果您实际研究了几个大型软件,您会发现大多数内存副本实际上复制的数据少于 32 字节,而复制超过 4 KiB 的数据几乎从未发生过。这意味着针对大量数据优化 memcpy()(以牺牲启动开销为代价,使小内存副本的速度变慢)是愚蠢的,而且您的优化只会使实际软件的性能更差。

标签: c++ assembly memcpy


【解决方案1】:

引用Intel:

"流式加载指令为 旨在加速数据传输 来自 USWC 内存类型。对于他人 内存类型,例如可缓存 (WB) 或 不可缓存(UC),指令 表现为典型的 16 字节 MOVDQA 加载指令。然而,未来 处理器可以使用流负载 其他内存类型的指令 (如 WB)作为暗示 应流式传输预期的缓存行 从内存直接到核心同时 最大限度地减少缓存污染。”

这就解释了为什么代码不起作用——内存是 WB 类型的。

【讨论】:

  • 如果您对这个»解决方案«(即 MOVNTDQA 不起作用)感到满意,您能否将此解决方案标记为已接受,以便其他人一眼就知道?
猜你喜欢
  • 2016-10-20
  • 1970-01-01
  • 2017-06-04
  • 1970-01-01
  • 2014-11-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-12-05
相关资源
最近更新 更多