3

我有两个函数,一个计算行中连续元素之间的差异,第二个计算列中值之间的连续差异。因此,一个会计算M[i][j+1] -M[i][j],第二个会做M[i+1][j] - M[i][j]M作为矩阵。我按如下方式实现它们 -

inline void firstFunction(uchar* input, uchar* output, size_t M, size_t N){

    for(int i=0; i < M; i++){
        for(int j=0; j <=N - 33; j+=32){

            auto pos = i*N + j;
            _mm256_storeu_epi8(output + pos, _mm256_sub_epi8(_mm256_loadu_epi8(input + pos + 1), _mm256_loadu_epi8(input + pos)));   
        
        }
    }
}
void secondFunction(uchar* input, uchar* output, size_t M, size_t N){

    for(int i = 0; i < M-1; i++){
//#pragma prefetch input : (i+1)*N : (i+1)*N + N
        for(int j = 0; j <N-33; j+=32){

            auto idx = i * N + j;
            auto idx_1 = (i+1)*N + j;

            _mm256_storeu_epi8(output + idx, _mm256_sub_epi8(_mm256_loadu_epi8(input + idx_1), _mm256_loadu_epi8(input + idx)));
        }
    }

但是,对它们进行基准测试,第一个和第二个函数的平均运行时间如下 -
firstFunction = 21.1432ms
secondFunction = 166.851ms

矩阵的大小是M = 9024N = 12032

对于类似的操作,这是运行时间的巨大增加。我怀疑这与内存访问和缓存有关,在第二种情况下,更多的周期用于从另一行获取内存。

所以我的问题分为两部分。

  1. 我对运行时差异的推理是否正确。
  2. 我该如何缓解。我的第一个想法是预取内存中的第二行并继续,但我无法预取动态计算的位置。如果_mm_prefetch问题确实与内存访问时间有关,将会有所帮助

我正在使用dpcpp编译器。编译选项为-g -O3 -fsycl -fsycl-targets=spir64 -mavx512f -mavx512vl -mavx512bw -qopenmp -liomp5 -lpthread. 此编译器具有pragma prefetch但不允许运行时计算的预取。但是,我真的很感激一些不是特定于编译器的东西,它也可能是特定于 GCC 的。

Edit1 - 刚试过_mm_prefetch,但也抛出error: argument to 'error: argument to '__builtin_prefetch' must be a constant integer _mm_prefetch(input + (i+1) * N, N);。所以还有一个问题,有什么方法可以预取运行时计算的内存位置?

TIA

4

0 回答 0