我怎么能加快这种方法

时间:2014-06-23 09:13:27

标签: c# math optimization for-loop simulation

我试图实现Simulating ocean water (PDF)中概述的iWave水面模拟,最后有一个代码提取。

特定方法是使用卷积核计算垂直导数

for(int ix = 6; ix < iwidth - 6; ix++)
{
    for(int iy = 6; iy < iheight - 6; iy++)
    {
        int index = ix + iwidth * iy;
        float vd = 0;

        // apply convolution
        for(int iix = -6; iix <= 6; iix++)
        {
            for(int iiy = -6; iiy <= 6; iiy++)
            {
                int iindex = ix + iix + iwidth * (iy + iiy);
                vd += kernel[iix + 6, iiy + 6] * height[iindex];
            }
        }
        vertical_derivative[index] = vd;
    }
}

在每个高度点(一个扁平的2x2阵列)卷积内核(2x2数组大小为13) 用于计算垂直导数。 当高度网格的大小(128x128)时,实时交互变得太慢,但我想要一个更大的网格。我怎么能加快速度呢?

3 个答案:

答案 0 :(得分:1)

进行卷积的一种更快的方法是利用身份FT(conv(f,g))= FT(f)FT(g),即两个函数的卷积的傅立叶变换是傅立叶变换的逐点积。因此conv(f,g)= FT ^ -1(FT(f)FT(g))其中FT ^ -1是逆傅立叶变换。使用快速傅里叶变换。

答案 1 :(得分:1)

我同意以某种方式使用显卡获得最高增益。

但请注意两种方法:

  1. 您可以将索引的一些基本算法移出最内层循环。 这将为您提供大约10%的加速。除了你使用的任何线程之外,这是值得做的。
  2. 只需使用Parallel.For内置语言功能;这将在CPU上并行化,并且非常易于使用。

        const int convolutionWidth = 6;
        Parallel.For(convolutionWidth, iwidth - convolutionWidth, ix =>
        {
            for (int iy = convolutionWidth; iy < iheight - convolutionWidth; iy++)
            {
                int index = ix + iwidth * iy;
                float vd = 0;
                // apply convolution
                for (int iix = -convolutionWidth; iix <= convolutionWidth; iix++)
                {
                    int iindex = ix + iix + iwidth * (iy - convolutionWidth);
                    for (int iiy = -convolutionWidth; iiy <= convolutionWidth; iiy++)
                    {
                        vd += kernel[iix + convolutionWidth, iiy + convolutionWidth] * height[iindex];
                        iindex += iwidth;
                    }
                }
                vertical_derivative[index] = vd;
            }
        });
    

答案 2 :(得分:0)

使用SIMD功能(如果您的硬件支持),这种情况可以高度优化。

但是,CLR目前尚未使用完整的SIMD功能。对于实验用途,您可以下载支持RyuJit

(see this link for more info)

主要思想是重构一下你的数据格式,以便为你的操作使用向量(而不仅仅是数字)

加速可以令人印象深刻(最高可达x6,具体取决于您的硬件)。