Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/308.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# C语言中的快速列表乘法_C# - Fatal编程技术网

C# C语言中的快速列表乘法

C# C语言中的快速列表乘法,c#,C#,一些背景知识,我正在尝试做一个大规模的建筑模拟 问题是我有一个自定义类型Point3D的列表,我想对它进行快速数组乘法。所以,在不同的时间步,我必须用Point3D乘以一个双倍值,我已经为每个Point3D重载了Point3D的乘法和除法运算,结果将存储在字典中。该字典的关键是不同的时间步长,其值是相应的位移 因为我有很多自由度,很多时间步长,上面的操作似乎非常慢。是否存在优化整个操作的方法 这是我当前的代码,速度非常慢。所以我需要一些想法来优化它 public static Dictionar

一些背景知识,我正在尝试做一个大规模的建筑模拟

问题是我有一个自定义类型Point3D的列表,我想对它进行快速数组乘法。所以,在不同的时间步,我必须用Point3D乘以一个双倍值,我已经为每个Point3D重载了Point3D的乘法和除法运算,结果将存储在字典中。该字典的关键是不同的时间步长,其值是相应的位移

因为我有很多自由度,很多时间步长,上面的操作似乎非常慢。是否存在优化整个操作的方法

这是我当前的代码,速度非常慢。所以我需要一些想法来优化它

public static Dictionary<double, List<Point3D>> ComputeTimeSeries(Dictionary<double, double> timeStep, List<Point3D> dofs)
{
   var timeSeries = new Dictionary<double, List<Point3D>>();
   foreach(var keyValue in timeStep)
   {
      // the point3d*double operation is already being overloaded.
      timeSeries.Add(keyValue.Key, dofs.Select(pt=>pt*keyValue.Value).ToList());  
   }
   return timeSeries;
}

注意:我目前仍然停留在.NET3.5。因此,PLINQ和TPL可能帮不上忙

我不是C专家,但可能

dofs.Select(pt=>pt*keyValue.Value).ToList()
部分可以从并行化中受益。使用SIMD指令和/或线程,可以并行执行dofs[0]*=keyValue.Value和dofs[1]*=keyValue.Value等

这段代码看起来很像本文中给出的第一个示例。也许你可以把上面的内容改写成

Parallel.For(0, dofs.Length, delegate(int i) {
  dofs[i] *= keyValue.Value;
});

对于初学者,您可以在创建新字典时使用容量参数来消除一些重新分配和复制:

 var timeSeries = new Dictionary<double, List<Point3D>>(timeStep.Count);


探查器将为您提供一些想法。 还有,试着逃离林克

public static Dictionary<double, List<Point3D>> ComputeTimeSeries(Dictionary<double, double> timeStep, List<Point3D> dofs)
{
   var timeSeries = new Dictionary<double, List<Point3D>>();
   foreach(var keyValue in timeStep)
   {
      List<double> lst = new List<double>();
      foreach (Point3D point in dofs)
         lst.Add(point* keyValue.Value);

      timeSeries.Add(keyValue.Key, lst);  // the point3d*double operation is already being overloaded.
   }
   return timeSeries;
}

如果可以在不同的字典中更改返回值,则可以将实际计算推迟到需要时进行

您可以删除.ToList并以以下内容结束:

public static Dictionary<double, IEnumerable<Point3D>> ComputeTimeSeries(Dictionary<double, double> timeStep, List<Point3D> dofs)
{
   var timeSeries = new Dictionary<double, List<Point3D>>();  
   foreach(var keyValue in timeStep)    
   {
      // the point3d*double operation is already being overloaded.
      timeSeries.Add(keyValue.Key, dofs.Select(pt=>pt*keyValue.Value));  
   } 
   return timeSeries; 
}

现在,计算将在开始枚举值时执行,而不是在ComputeTimeSeries方法中执行。这不会加快计算速度,但您可能会及时将它们分散开来,甚至可能跨越多个线程。

我会尝试以下方法:

public static Dictionary<double, Point3D[]> ComputeTimeSeries(Dictionary<double,    double> timeStep, Point3D[] dofs)
{
   var timeSeries = new Dictionary<double, Point3D[]>();
   foreach(var keyValue in timeStep)
   {
      var tempArray = new Point3D[dofs.Length];
      for (int index=0; index < dofs.Length; index++)
          tempArray[index] = dofs[index] * keyValue.Value;
      timeSeries.Add(keyValue.Key, tempArray);  
   }
   return timeSeries;
}

使用Select/ToList更具可读性,但与简单的乘法相比,额外的接口调用非常昂贵。

我仍然停留在.net 3.5上,因此所有很酷的PLINQ和TPL技巧可能都不会有帮助。我非常确定上述代码是瓶颈,知道还有什么地方可以分析吗?问题中的代码有多个部分,评测是一个好主意。可能是。ToList是瓶颈或乘法。或者任何.Add方法。不幸的是,我仍然停留在.NET3。5@Ngu:但一定要使用容量。timestep值到底是多少?这是某种形式的采样时间吗?时间步长之间的间隔是否不同?只是想知道是否必须使用字典类型?timestep值是采样时间的一种形式,值之间有规律地增加。时间步之间的间隔相同。不,没有必要使用字典。但是使用字典是一个问题吗?如果您不需要通过键快速访问,那么当然最好使用数组或简单列表。这里的根本问题不是:我们如何在C中高效地执行一系列乘法?如果是这样,我们应该看看矩阵代数库吗?字典类型的使用使问题复杂化了。如果样本之间的间隔是固定的,那么将数据样本存储在数组中并使用矩阵运算会更快。但如果枚举不止一次,这也意味着计算要进行多次。此外:我怀疑乘法运算是真正的瓶颈。对于每一次乘法,都有几个接口/委托调用,这比乘法要昂贵得多。这取决于序列的使用方式,但是是的。他必须意识到这一点。@nikie:一种优化方法是在foreach循环之外声明tempArray,以避免多次分配的风险。我认为额外的分配不会被优化。@Brian:我不明白。如果我只分配一个实例,那么字典将如何包含多个不同版本的数据?
public static Dictionary<double, IEnumerable<Point3D>> ComputeTimeSeries(Dictionary<double, double> timeStep, List<Point3D> dofs)
{
   var timeSeries = new Dictionary<double, List<Point3D>>();  
   foreach(var keyValue in timeStep)    
   {
      // the point3d*double operation is already being overloaded.
      timeSeries.Add(keyValue.Key, dofs.Select(pt=>pt*keyValue.Value));  
   } 
   return timeSeries; 
}
public static Dictionary<double, Point3D[]> ComputeTimeSeries(Dictionary<double,    double> timeStep, Point3D[] dofs)
{
   var timeSeries = new Dictionary<double, Point3D[]>();
   foreach(var keyValue in timeStep)
   {
      var tempArray = new Point3D[dofs.Length];
      for (int index=0; index < dofs.Length; index++)
          tempArray[index] = dofs[index] * keyValue.Value;
      timeSeries.Add(keyValue.Key, tempArray);  
   }
   return timeSeries;
}