gpt4 book ai didi

c# - 寻找一种更快的方法来在 C# 中对数组求和

转载 作者:行者123 更新时间:2023-11-30 19:58:32 26 4
gpt4 key购买 nike

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

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;
}

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

最佳答案

如果您知道您正在以有点低效的顺序迭代维度这一事实,您将获得从 270 毫秒到 0 毫秒的代码,这会导致 false sharing .您实际上是在并行化“宽度”,而不是高度。您可能对数组在内存中的存储方式感到困惑。

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

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

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

这花了我 800 毫秒到 150 毫秒,同时具有相同的维度,只是交换了一些东西。

关于c# - 寻找一种更快的方法来在 C# 中对数组求和,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26548756/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com