我有两个函数,一个计算行中连续元素之间的差异,第二个计算列中值之间的连续差异。因此,一个会计算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 = 9024
和N = 12032
对于类似的操作,这是运行时间的巨大增加。我怀疑这与内存访问和缓存有关,在第二种情况下,更多的周期用于从另一行获取内存。
所以我的问题分为两部分。
- 我对运行时差异的推理是否正确。
- 我该如何缓解。我的第一个想法是预取内存中的第二行并继续,但我无法预取动态计算的位置。如果
_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