Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/amazon-s3/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/url/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Optimization 使用SSE、AVX和OpenMP进行快速内存转置_Optimization_Openmp_Sse_Transpose_Avx - Fatal编程技术网

Optimization 使用SSE、AVX和OpenMP进行快速内存转置

Optimization 使用SSE、AVX和OpenMP进行快速内存转置,optimization,openmp,sse,transpose,avx,Optimization,Openmp,Sse,Transpose,Avx,在C/C++中,我需要一个用于高斯卷积函数的快速内存转置算法。我现在做的是 convolute_1D transpose convolute_1D transpose 结果表明,使用这种方法时,滤波器尺寸必须大(或比我预期的大),或者转置时间比卷积时间长(例如,对于1920x1080矩阵,卷积时间与滤波器尺寸为35的转置时间相同)。我目前使用的转置算法使用循环阻塞/平铺以及SSE和OpenMP。我尝试了一个使用AVX的版本,但没有更快。有没有关于我如何加快速度的建议 inline void t

在C/C++中,我需要一个用于高斯卷积函数的快速内存转置算法。我现在做的是

convolute_1D
transpose
convolute_1D
transpose
结果表明,使用这种方法时,滤波器尺寸必须大(或比我预期的大),或者转置时间比卷积时间长(例如,对于1920x1080矩阵,卷积时间与滤波器尺寸为35的转置时间相同)。我目前使用的转置算法使用循环阻塞/平铺以及SSE和OpenMP。我尝试了一个使用AVX的版本,但没有更快。有没有关于我如何加快速度的建议

inline void transpose4x4_SSE(float*A,float*B,const int lda,const int ldb){
__m128第1行=_mm_load_ps(&A[0*lda]);
__m128第2行=_mm_load_ps(&A[1*lda]);
__m128第3行=_mm_load_ps(&A[2*lda]);
__m128第4行=_mm_load_ps(&A[3*lda]);
_MM_TRANSPOSE4_PS(第1行、第2行、第3行、第4行);
_mm_商店(第1行为&B[0*ldb]);
_mm_商店(和B[1*ldb],第2行);
_mm_store_ps(&B[2*ldb],第3行);
_mm_store_ps(&B[3*ldb],第4行);
}
//块大小=16效果最佳
内联无效转置块(浮点*A、浮点*B、常数整数n、常数整数m、常数整数lda、常数整数ldb、常数整数块大小){
#pragma-omp并行

对于(int i=0;i,我想最好的办法是尝试将卷积和转置结合起来,即在转置过程中写出卷积转置的结果。几乎可以肯定的是,转置过程中内存带宽有限,因此减少转置过程中使用的指令数量并没有真正的帮助(因此使用AVX缺乏改进)。减少数据传输次数将为您带来最好的性能改进。

FWIW,在3年前的i7M笔记本电脑核心CPU上,这种朴素的4x4转置几乎比您的SSE版本慢,而在更新的Intel Xeon E5-2630 v2@2.60GHz桌面CPU上则快了近40%

inline void transpose4x4_naive(float*A,float*B,const int lda,const int ldb){
常量float r0[]={A[0],A[1],A[2],A[3]};//是否改为memcpy?
A+=lda;
常量浮点r1[]={A[0],A[1],A[2],A[3]};
A+=lda;
常量浮点r2[]={A[0],A[1],A[2],A[3]};
A+=lda;
常量浮点r3[]={A[0],A[1],A[2],A[3]};
B[0]=r0[0];
B[1]=r1[0];
B[2]=r2[0];
B[3]=r3[0];
B+=ldb;
B[0]=r0[1];
B[1]=r1[1];
B[2]=r2[1];
B[3]=r3[1];
B+=ldb;
B[0]=r0[2];
B[1]=r1[2];
B[2]=r2[2];
B[3]=r3[2];
B+=ldb;
B[0]=r0[3];
B[1]=r1[3];
B[2]=r2[3];
B[3]=r3[3];
}
奇怪的是,老式笔记本电脑的CPU速度比双核E5-2630 v2台式机快两倍,但情况不同:)


否则,您可能也会感兴趣(需要立即登录…

考虑一下这个4x4转置

struct MATRIX {
    union {
        float  f[4][4];
        __m128 m[4];
        __m256 n[2];
    };
};
MATRIX myTranspose(MATRIX in) {

    // This takes 15 assembler instructions (compile not inline), 
    // and is faster than XMTranspose
    // Comes in like this  1  2  3  4  5  6  7  8
    //                     9 10 11 12 13 14 15 16
    //
    // Want the result     1  5  9 13  2  6 10 14
    //                     3  7 11 15  4  8 12 16

    __m256 t0, t1, t2, t3, t4, t5, n0, n1;
    MATRIX result;

    n0 = in.n[0];                                               // n0 =  1,  2,  3,  4,  5,  6,  7,  8
    n1 = in.n[1];                                               // n1 =  9, 10, 11, 12, 13, 14, 15, 16
    t0 = _mm256_unpacklo_ps(n0, n1);                            // t0 =  1,  9,  2, 10,  5, 13,  6, 14
    t1 = _mm256_unpackhi_ps(n0, n1);                            // t1 =  3, 11,  4, 12,  7, 15,  8, 16

    t2 = _mm256_permute2f128_ps(t0, t1, 0x20);                  // t2 =  1,  9,  2, 10,  3, 11,  4, 12 
    t3 = _mm256_permute2f128_ps(t0, t1, 0x31);                  // t3 =  5, 13,  6, 14,  7, 15,  8, 16

    t4 = _mm256_unpacklo_ps(t2, t3);                            // t2 =  1,  5,  9, 13,  3,  7, 11, 15
    t5 = _mm256_unpackhi_ps(t2, t3);                            // t3 =  2,  6, 10, 14,  4,  8, 12, 16

    result.n[0] = _mm256_permute2f128_ps(t4, t5, 0x20);         // t6 =  1,  5,  9, 13,  2,  6, 10, 14
    result.n[1] = _mm256_permute2f128_ps(t4, t5, 0x31);         // t7 =  3,  7, 11, 15,  4,  8, 12, 16
    return result;
}

好的方面。我之所以要做转置,首先是因为读取不连续的数据会导致大量缓存命中。因此,缓存命中和进行转置的时间之间有一场斗争。我不确定写出转置的结果是否有助于卷积。不过,可能我必须想出一个不同的方法L较小过滤器大小的算法。我将对适合二级或三级缓存的较小矩阵大小进行一些测试,然后返回给您。在本例中,您可能对AVX没有更好表现的原因是正确的。我在64x64、192x192、896x896和5008x5008上尝试了转置。这些应该对应于我的l1、L2、L3和主内存区域。AVX对于64x64(一级缓存),它仅略优于SSE。我在测试中关闭了OpenMP。您正在通过2个1D过程(可分离的高斯模糊)进行2D高斯卷积?为什么在第一次读取数据时数据不连续?似乎您应该能够读取水平模糊过程的连续数据,并写出转置后的结果,以便在第二次垂直过程中再次连续读取,并将转置后的结果写回原始布局。这也可能值得一看这是在GPU上快速实现的。你可以在块中一次完成完整的2D模糊-在大约一级缓存大小的块中读取整个2D内核输入区域,然后在块上进行两次可分离的1D传递,并写入一个单独的输出图像。好吧,该链接已经失效。我想我已经找到了新链接,并在上面对其进行了更新,但需要进行更新ogin now.Haswell只有一个洗牌单元,但Nehalem通过IvB有两个,洗牌吞吐量为每0.5c一个。(.)E5 xxxx v2是IvyBridge,所以可能不是这样。除非你使用多线程运行,否则我想知道为什么你在比较笔记本电脑和Xeon时会提到内核计数。
\uUm128 xmm[4]
\uuuuum256ymm[2]
将是更为明显的名称。但这种结合是一种非常丑陋的黑客行为,如果你滥用它,很容易编译成低效的代码。