了解Intel Xeon PHi 7210上的矩阵乘法技术

问题描述 投票:0回答:1

我有以下的工作程序,它能正确地产生结果,但我对一些统计数字感到困惑。设置是这样的。

  1. 硬件:Intel Xeon Phi处理器 7210
  2. 软件。两个NxN矩阵的乘法(我的例子是512x512)。
  3. 数据结构。所有3个矩阵都在高带宽内存中进行malloc'ed(即16GB mcdram)

代码是。

void MatrixMultiply(img_in1, img_in2, img_out, myRank, nRanks)
{
    for (int i=startingRow ; i<endingRow ; i++)     //no of rows of first matrix divided on per process basis
    {
        for (int j=0 ; j<M1Cdim ; j++)          //no of cols of first matrix
        {
            int temp = 0;
            for(int k=0 ; k<M2Rdim ; k++)       //no of rows of second matrix
            {
            temp += in1[i*M1Rdim+k] *  in2[k*M2Rdim+j]; //out(i,j) +=  in1(i,k) * in2(k,j)
        }
        out[i*M1Rdim+j] = temp;
    }
    }
}

main()
{
  for (int i = 1; i <= 10; i++) 
  {
    MPI_Barrier(MPI_COMM_WORLD);
    const double t0 = omp_get_wtime();
    MatrixMultiply(img_in1, img_in2, img_out, myRank, nRanks);
    MPI_Barrier(MPI_COMM_WORLD);
    const double t1 = omp_get_wtime();

    const double ts   = t1-t0;      // time in seconds
    const double tms  = ts*1.0e3;   // time in milliseconds
    const double gbps = double(sizeof(P)*2*img_in1.height*img_in1.width*img_in2.height)*1e-9/ts;    // bandwidth in GB/s
    const double fpps = double(2*img_in1.height*img_in1.width*img_in2.height)*1e-9/ts;          // performance in GFLOP/s

    if (myRank == 0) 
    {   
      printf("%5d %15.3f %15.3f %15.3f %s\n", i, tms, gbps, fpps);
    }
  }
}

The statistics I am getting are:

 Step        Time, ms            GB/s         GFLOP/s
    1           2.306         116.408         116.408
    2           2.334         115.017         115.017
    3           2.297         116.855         116.855
    4           2.295         116.964         116.964 
    5          16.692          16.082          16.082 
    6          11.468          23.407          23.407 
    7           2.299         116.758         116.758 
    8           2.291         117.171         117.171 
    9           2.295         116.964         116.964 
   10          10.792          24.874          24.874 

所以我的问题是:

为什么第5、6、10次迭代的结果比其他迭代的差?

我的怀疑是,即使数据被放置在高带宽内存(mcdram)中,但代码本身是从缓存中执行的,所以可能会受到影响。虽然整个程序非常小,如54KB,但如果运行在共享服务器上,那么一些迭代可能会从指令缓存中被驱逐,导致性能下降。

performance benchmarking cpu-architecture cpu-cache xeon-phi
1个回答
1
投票

这个矩阵乘法代码是 效率低下!

的确,这条线 in2[k*M2Rdim+j] 有可能导致 高速缓存 于是 计算时间的高不稳定性 如果需要经常从MCD-RAM中重新加载线路。虽然MCD-RAM有很高的带宽,但它也有很高的延迟(类似于DDR-RAM的延迟)。在这种情况下,延迟可能是一个很大的问题。

具体来说,在矩阵的一列中跨下一列,对于空间定位来说是很糟糕的。 而当矩阵维度是2的幂数时,情况就更糟糕了:你很可能在缓存上出现冲突失误,因为所有这些缓存行都会在集关联缓存中别名到同一个集。 这可能会导致缓存打乱,即使工作集很小。


因此,请使用 BLAS 函数(来自MKL、OpenBLAS、ATLAS等)! 它们的优化程度远高于此。如果你不能,请考虑改进这个代码。你可以找到一个相当不错的解释,你可以这样做。此处. 我想,提速10以上是很容易实现的。

我还建议你 概况 使用 perf 或 VTune 等工具对您的代码进行分析。硬件事件 (如L1L2缓存操作),并确认拒绝现金粉碎假说,以及帮助你改进这段代码。

© www.soinside.com 2019 - 2024. All rights reserved.