【发布时间】:2017-04-28 23:29:14
【问题描述】:
我正在努力在下面的代码中使用 Parallel.For 而不是 for 循环。 由于 CoefficientVector 向量数组的大小相当大,所以对我来说只重置数组元素值而不是为每次迭代创建新值是有意义的。
我尝试用 Parallel For 替换外循环;并假设并行的每个分区由一个单独的线程运行,将拥有自己的 CoefficientVector 类的副本,因此对我来说,为每个线程拥有一个 CoefficientVector 对象的实例并重置向量元素而不是重新创建数组。我虽然发现很难在 Parallel For 上进行这种优化(?)。谁能帮忙。
static void Main(string[] args)
{
System.Diagnostics.Stopwatch timer = new System.Diagnostics.Stopwatch();
timer.Start();
int numIterations = 20000;
int numCalpoints = 5000;
int vecSize = 10000;
CalcPoint[] calcpoints = new CalcPoint[numCalpoints];
CoefficientVector coeff = new CoefficientVector();
coeff.vectors = new Vector[vecSize];
//not sure how to correctly use Parallel.For here
//Parallel.For(0, numCalpoints, =>){
for (int i = 0; i < numCalpoints;i++)
{
CalcPoint cp = calcpoints[i];
//coeff.vectors = new Vector[vecSize];
coeff.ResetVectors();
//doing some operation on the matrix n times
for (int n = 0; n < numIterations; n++)
{
coeff.vectors[n].x += n;
coeff.vectors[n].y += n;
coeff.vectors[n].z += n;
}
cp.result = coeff.GetResults();
}
Console.Write(timer.Elapsed);
Console.Read();
}
}
class CoefficientVector
{
public Vector[] vectors;
public void ResetVectors()
{
for (int i = 0; i < vectors.Length; i++)
{
vectors[i].x = vectors[i].y = vectors[i].z = 0;
}
}
public double GetResults()
{
double result = 0;
for (int i = 0; i < vectors.Length; i++)
{
result += vectors[i].x * vectors[i].y * vectors[i].z;
}
return result;
}
}
struct Vector
{
public double x;
public double y;
public double z;
}
struct CalcPoint
{
public double result;
}
【问题讨论】:
-
如果你想重置向量数组中的向量,为什么不使用
Array.Clear(...)? Array.Clear(...) 将每个数组元素设置为其默认值。这在这里可以工作,因为结构是值类型,并且将 Vector 结构设置为其默认值意味着将其每个字段设置为其默认值(对于数字类型为零)... -
谢谢@elgonzo。也许我没有正确解释它。但是每个计算点都需要保持自己的结果。使用 Parallel For 和 Array.Clear(...) 将改变其他计算点的结果。这是正确的吗?
-
抱歉,误解了您的问题。只需使用 Parallel.Foreach 编写代码。不要担心优化。如果您觉得即使使用 Parallel.Foreach 代码仍然太慢,请分析 Parallel.Foreach 执行的代码以查看进一步优化工作的回报。 (我假设您在这里给出的代码有些简化,实际矩阵计算要复杂一些)
-
@elgonzo。我喜欢你在认真对待这种优化时表现得很冷静:)
-
@elgonzo 正如你所说。计算实际上是使用矩阵系数进行光线追踪,耗时耗力。
标签: c# parallel.foreach