gpt4 book ai didi

C#.net 多线程

转载 作者:可可西里 更新时间:2023-11-01 07:44:03 25 4
gpt4 key购买 nike

我正在尝试在名为 Grasshopper(Rhino3D 的一部分)的包中使用 C#.net 优化一些数学运算。该操作非常简单,但必须执行的列表很大,而且可能会变得更大。

我在我的 C# 脚本中使用 Parallel.ForEach 和列表,我得到的最终结果数量低于预期。这很可能是由于 list.add 不是线程安全的(或者在我构建它的软件中不是线程安全的)。

  private void RunScript(double z, int x, List<double> y, ref object A)
{
List<double> temp = new List<double>();
double r;
System.Threading.Tasks.Parallel.ForEach(y, numb =>
{
r = Math.Pow((numb * x), z);
temp.Add(r);
});
A = temp;

请帮助我想出一种简单有效的方法来使用 CPU 多线程对数百个值运行这个简单的数学运算(或者如果您对 GPU CUDA 有任何建议)。

我希望晦涩而具体的软件不会打扰您,因为据我所知,它的性能与普通的 C#.Net/Python/VB.Net 相同。

最佳答案

你猜对了,List<T>不是线程安全的。您必须同步访问它的任何实例。

一个选择是在每个任务中简单地同步:

private void RunScript(double z, int x, List<double> y, ref object A)
{
List<double> temp = new List<double>();
object l = new object();
System.Threading.Tasks.Parallel.ForEach(y, numb =>
{
double r = Math.Pow((numb * x), z);
lock (l) temp.Add(r);
});
A = temp;
}

注意:您的代码中还有另一个错误。您共享相同的 r所有任务之间的变量,这可能导致相同的值被添加到结果中两次或更多次,而其他值被排除在外。我通过简单地将变量声明移动到用于 ForEach() 的匿名方法的主体来修复该错误。打电话。


另一种选择是认识到您事先知道您将获得多少结果,因此可以简单地初始化一个足够大的数组以包含所有结果:

private void RunScript(double z, int x, List<double> y, ref object A)
{
double[] results = new double[y.Count];
System.Threading.Tasks.Parallel.For(0, y.Count, i =>
{
// read-only access of `y` is thread-safe:
results[i] = Math.Pow((y[i] * x), z);
});
A = new List<double>(results);
}

没有两个线程会尝试访问 results 中的同一个元素数组,并且数组本身永远不会改变(即重新分配),因此这是完全线程安全的。

上面假设你确实需要一个 List<double>作为输出对象。当然,如果数组满足,那么你可以直接分配results。至 A而不是将其传递给 List<T>构造函数在最后创建一个全新的对象。

关于C#.net 多线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29709857/

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