寻找在 C# 中对数组求和的更快方法

Pio*_*iec 2 c#

在我目前正在开发的应用程序中,我必须有效地对相当大的向量数组求和。这是我的代码:

public List<double[, ,]> normalMaps;

public double[, ,] Mix(double[] weights, double gain)
{
    int w, h;
    w = normalMaps[0].GetLength(0);
    h = normalMaps[0].GetLength(1);

    double[, ,] ret = new double[w, h, 3];
    int normcount = normalMaps.Count;

    //for (int y = 0; y < h; y++)
    Parallel.For(0, h, y =>            
    {
        for (int x = 0; x < w; x++)
        {
            for (int z = 0; z < normcount; z++) 
            {
                ret[x, y, 0] += normalMaps[z][x, y, 0] * weights[z];
                ret[x, y, 1] += normalMaps[z][x, y, 1] * weights[z];
                ret[x, y, 2] += normalMaps[z][x, y, 2] * weights[z];
            }
            ret[x, y, 0] *= gain;
            ret[x, y, 1] *= gain;
            ret[x, y, 2] *= gain;

            ret[x, y, 0] = Math.Max(-1, Math.Min(1, ret[x, y, 0]));
            ret[x, y, 1] = Math.Max(-1, Math.Min(1, ret[x, y, 1]));
            ret[x, y, 2] = Math.Max(-1, Math.Min(1, ret[x, y, 2]));

            double retnorm = Math.Sqrt(ret[x, y, 0] * ret[x, y, 0] + ret[x, y, 1] * ret[x, y, 1] + ret[x, y, 2] * ret[x, y, 2]);
            ret[x, y, 0] /= retnorm;
            ret[x, y, 1] /= retnorm;
            ret[x, y, 2] /= retnorm;

        }
    });

    return ret;
}
Run Code Online (Sandbox Code Playgroud)

现在,当我尝试对 7 个 1024*1024 的 3 分量向量数组求和时,该操作在我的笔记本电脑上需要 320 毫秒。使代码多线程已经给了我巨大的性能提升。但我需要让它更快。我怎样才能进一步优化它?我已经看到我可以使用一个简单的数组而不是 List<>,这会使代码更快,但不会太多。真的没有什么可以优化了吗?我正在考虑将这个东西移到 GPU 上,但这只是一个想法。有人可以帮我吗?提前致谢。

Ert*_*maa 5

如果您知道您正在以低效的顺序迭代维度,这会导致错误共享,那么您的代码将从 270 毫秒到 0 毫秒。您基本上是在并行化“宽度”,而不是高度。您可能对数组在内存中的存储方式感到困惑。

错误共享并不是唯一的问题,由于计算机的工作方式,您以缓存低效的方式迭代事物

通常数组定义应该是myArray[HEIGHT, WIDTH]为了和内存存储保持一致,迭代的时候height应该在最外层。

Parallel.For(0, w, x =>            
{
    for (int y = 0; y < h; y++)
    {
       ...
    }
}
Run Code Online (Sandbox Code Playgroud)

这使我从 800 毫秒到 150 毫秒,同时具有相同的尺寸,只需交换一些东西。

  • 不用担心,我学到了一些东西,即检查这个:http://stackoverflow.com/questions/468832/why-are-multi-dimensional-arrays-in-net-slower-than-normal-arrays 基准似乎表明那个多维数组比锯齿状数组慢 2 倍,哈哈。也许您甚至可以达到 75 毫秒。 (2认同)