背景
如果您一直关注我的帖子,我试图复制Kazushige Goto关于方阵乘法的开创性论文中的结果C = AB.我在这里可以找到关于这个主题的最后一篇文章.在我的代码版本中,我遵循Goto的内存分层和打包策略2x8以及C使用128位SSE3内在函数的内核计算块.我的CPU是i5-540M,超线程关闭.有关我的硬件的其他信息可以在另一篇文章中找到,并在下面重复.
我的硬件
我的CPU是Intel i5 - 540M.您可以在cpu-world.com上找到相关的CPUID信息.微体系结构是Nehalem(westmere),因此理论上每循环每个核心可以计算4个双精度触发器.我将只使用一个核心(没有OpenMP),所以对于超线程关闭和4步Intel Turbo Boost,我应该会看到一个高峰( 2.533 Ghz + 4*0.133 Ghz ) * ( 4 DP flops/core/cycle ) * ( 1 core ) = 12.27 DP Gflops.作为参考,两个核心都运行在峰值,英特尔Turbo Boost提供了两步加速,我应该获得理论峰值22.4 DP Gflops.
我的软件
Windows7 64位,但MinGW/GCC 32位由于我的电脑限制.
这次有什么新鲜事?
2x4块C.这提供了更好的性能,并且与Goto所说的一致(一半寄存器用于计算C).我试过很多大小:1x8,2x8,2x4,4x2,2x2,4x4.clock().问题
我正在学习HPC和代码优化.我试图在Goto的开创性矩阵乘法论文(http://www.cs.utexas.edu/users/pingali/CS378/2008sp/papers/gotoPaper.pdf)中复制结果.尽管我付出了最大努力,但我无法超过理论CPU最高性能的50%.
背景
请参阅此处的相关问题(优化的2x2矩阵乘法:慢速装配与快速SIMD),包括有关我的硬件的信息
我尝试过的
这篇相关论文(http://www.cs.utexas.edu/users/flame/pubs/blis3_ipdps14.pdf)很好地描述了Goto的算法结构.我在下面提供了我的源代码.
我的问题
我要求一般帮助.我一直在研究这个问题太久了,已经尝试了很多不同的算法,内联汇编,各种尺寸的内核(2x2,4x4,2x8,...,mxn m和n大),但我似乎无法打破50%CPU Gflops.这纯粹是出于教育目的,而不是作业.
源代码
希望是可以理解的.如果没有请问.我设置了宏结构(for循环),如上面第2篇文章中所述.我按照两篇论文中的讨论打包矩阵,并在图11中以图形方式显示(http://www.cs.utexas.edu/users/flame/pubs/BLISTOMSrev2.pdf).我的内核计算2x8块,因为这似乎是Nehalem架构的最佳计算(参见GotoBLAS源代码 - 内核).内核基于计算排名1更新的概念,如此处所述(http://code.google.com/p/blis/source/browse/config/template/kernels/3/bli_gemm_opt_mxn.c)
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <string.h>
#include <x86intrin.h>
#include <math.h>
#include <omp.h>
#include <stdint.h>
// define some prefetch functions
#define PREFETCHNTA(addr,nrOfBytesAhead) \
_mm_prefetch(((char *)(addr))+nrOfBytesAhead,_MM_HINT_NTA)
#define PREFETCHT0(addr,nrOfBytesAhead) \
_mm_prefetch(((char *)(addr))+nrOfBytesAhead,_MM_HINT_T0)
#define PREFETCHT1(addr,nrOfBytesAhead) \
_mm_prefetch(((char *)(addr))+nrOfBytesAhead,_MM_HINT_T1)
#define PREFETCHT2(addr,nrOfBytesAhead) \
_mm_prefetch(((char *)(addr))+nrOfBytesAhead,_MM_HINT_T2)
// define a min function
#ifndef min
#define min( a, b ) ( …Run Code Online (Sandbox Code Playgroud) 问题
我一直在研究HPC,特别是使用矩阵乘法作为我的项目(参见我在配置文件中的其他帖子).我在那些方面取得了不错的成绩,但还不够好.我退后一步看看我能用点积计算做得多好.
点积与矩阵乘法
点积更简单,可以让我测试HPC概念,而无需处理打包和其他相关问题.缓存阻塞仍然是一个问题,这是我的第二个问题.
算法
乘以n相应的元件以两种double阵列A和B与它们求和.一个double组装点积仅仅是一系列的movapd,mulpd,addpd.以一种聪明的方式展开和排列,可以使用movapd/ mulpd/ addpd在不同xmm寄存器上操作的组,因此是独立的,优化流水线操作.当然,事实证明,这与我的CPU无序执行无关.另请注意,重新安排需要剥离最后一次迭代.
其他假设
我不是在写一般点产品的代码.代码是针对特定尺寸的,我不处理边缘情况.这只是为了测试HPC概念并查看我可以获得的CPU使用类型.
结果
编译gcc -std=c99 -O2 -m32 -mincoming-stack-boundary=2 -msse3 -mfpmath=sse,387 -masm=intel.我和平时不同的电脑.这台计算机有一个i5 540m可以2.8 GHz * 4 FLOPS/cycle/core = 11.2 GFLOPS/s per core在两步英特尔Turbo Boost后获得(两个核心现在都在,所以它只有2步...如果我关掉一个核心,可以进行4步增强).设置为使用一个线程运行时,32位LINPACK大约为9.5 GFLOPS/s.
N Total Gflops/s Residual
256 5.580521 1.421085e-014
384 5.734344 -2.842171e-014
512 5.791168 0.000000e+000
640 5.821629 0.000000e+000
768 5.814255 2.842171e-014
896 5.807132 …Run Code Online (Sandbox Code Playgroud) 问题
我正在研究高性能矩阵乘法算法,如OpenBLAS或GotoBLAS,我正在尝试重现一些结果.这个问题涉及矩阵乘法算法的内核.具体来说,我正在研究计算C += AB,在我的CPU的峰值速度下,在哪里A和B是2x2类型的矩阵double.有两种方法可以做到这一点.一种方法是使用SIMD指令.第二种方法是使用SIMD寄存器直接在汇编代码中编码.
到目前为止我看过的是什么
所有相关论文,课程网页,许多SO Q&As处理主题(太多无法列出),我已经在我的计算机上编译了OpenBLAS,查看了OpenBLAS,GotoBLAS和BLIS源代码,Agner的手册.
硬件
我的CPU是Intel i5 - 540M.您可以在cpu-world.com上找到相关的CPUID信息.微体系结构是Nehalem(westmere),因此理论上每循环每个核心可以计算4个双精度触发器.我将只使用一个核心(没有OpenMP),所以对于超线程关闭和4步Intel Turbo Boost,我应该会看到一个高峰( 2.533 Ghz + 4*0.133 Ghz ) * ( 4 DP flops/core/cycle ) * ( 1 core ) = 12.27 DP Gflops.作为参考,两个核心都运行在峰值,英特尔Turbo Boost提供了两步加速,我应该获得理论峰值22.4 DP Gflops.
建立
我将我的2x2矩阵声明为double并使用随机条目对其进行初始化,如下面的代码片段所示.
srand(time(NULL));
const int n = 2;
double A[n*n];
double B[n*n];
double C[n*n];
double T[n*n];
for(int i = 0; i < n*n; i++){
A[i] = (double) rand()/RAND_MAX; …Run Code Online (Sandbox Code Playgroud)