Tag: openmp sse

最多不能超过50%。 矩阵乘法的理论性能

问题 我正在学习HPC和代码优化。 我试图在Goto的开创性矩阵乘法论文( http://www.cs.utexas.edu/users/pingali/CS378/2008sp/papers/gotoPaper.pdf )中复制结果。 尽管我付出了最大的努力,但我无法超过理论CPU最高性能的50%。 背景 请参阅此处的相关问题( 优化的2×2矩阵乘法:慢速assembly与快速SIMD ),包括有关我的硬件的信息 我尝试过的 这篇相关论文( http://www.cs.utexas.edu/users/flame/pubs/blis3_ipdps14.pdf )对Goto的算法结构有很好的描述。 我在下面提供了我的源代码。 我的问题 我要求一般帮助。 我一直在研究这个问题太久了,尝试了很多不同的算法,内联汇编,各种尺寸的内核(2×2,4×4,2×8,…,mxn m和n大),但我似乎无法打破50%CPU Gflops 。 这纯粹是出于教育目的,而不是作业。 源代码 希望是可以理解的。 请问是否。 我按照上面第2篇文章中的描述设置了宏结构(for loops)。 我按照两篇论文中的讨论打包矩阵,并在图11中以图形方式显示( http://www.cs.utexas.edu/users/flame/pubs/BLISTOMSrev2.pdf )。 我的内核计算2×8块,因为这似乎是Nehalem架构的最佳计算(参见GotoBLAS源代码 – 内核)。 内核基于计算排名1更新的概念,如此处所述( http://code.google.com/p/blis/source/browse/config/template/kernels/3/bli_gemm_opt_mxn.c ) #include #include #include #include #include #include #include #include // define some prefetch functions #define PREFETCHNTA(addr,nrOfBytesAhead) \ _mm_prefetch(((char *)(addr))+nrOfBytesAhead,_MM_HINT_NTA) #define […]

使用SSE / AVX进行OpenMP减少

我想使用OpenMP和SIMD对arrays进行减少。 我读到OpenMP的减少相当于: inline float sum_scalar_openmp2(const float a[], const size_t N) { float sum = 0.0f; #pragma omp parallel { float sum_private = 0.0f; #pragma omp parallel for nowait for(int i=0; i<N; i++) { sum_private += a[i]; } #pragma omp atomic sum += sum_private; } return sum; } 我从以下链接得到了这个想法: http : //bisqwit.iki.fi/story/howto/openmp/#ReductionClause但是atomic也不支持复杂的运算符。 我所做的是用关键替换primefaces并用OpenMP和SSE实现这种减少: #define ROUND_DOWN(x, s) […]

与SSE并行的前缀(累计)总和

我正在寻找有关如何与SSE进行并行前缀和的一些建议。 我有兴趣在一系列的整数,浮点数或双精度数上做这个。 我想出了两个解决方案。 一个特例和一般情况。 在这两种情况下,解决方案在与OpenMP并行的两次传递中在arrays上运行。 对于特殊情况,我在两次传球时使用SSE。 对于一般情况,我只在第二遍使用它。 我的主要问题是如何在一般情况下的第一遍中使用SSE? 以下链接simd-prefix-sum-on-intel-cpu显示字节的改进,但不是32位数据类型。 特殊情况称为特殊情况的原因是它要求数组采用特殊格式。 例如,让我们假设浮点数组中只有16个元素。 然后,如果数组像这样重新排列(结构数组结构): a[0] a[1] …a[15] -> a[0] a[4] a[8] a[12] a[1] a[5] a[9] a[13]…a[3] a[7] a[11] a[15] SSE垂直总和可用于两个通道。 但是,只有当数组已经采用特殊格式并且输出可以以特殊格式使用时,这才有效。 否则,必须在输入和输出上进行昂贵的重新排列,这将使其比一般情况慢得多。 也许我应该考虑一个不同的前缀和算法(例如二叉树)? 一般情况的代码: void prefix_sum_omp_sse(double a[], double s[], int n) { double *suma; #pragma omp parallel { const int ithread = omp_get_thread_num(); const int nthreads = […]