在 Parallel For 中使用共享变量
Using shared variable in Parallel For
我正在努力在下面的代码中使用 Parallel.For 而不是 for 循环。
由于 CoefficientVector 向量数组的大小相当大,因此对我来说只重置数组元素值而不是为每次迭代创建新的值是有意义的。
我尝试用Parallel For替换外层循环;并假设并行的每个分区,运行 通过一个单独的线程,将拥有它自己的 CoefficientVector class 副本,因此对我来说有意义(?)每个 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;
}
Parallel.For
方法目前有12个overloads. Besides the variations of int
, long
, ParallelOptions
and ParallelState
action arguments you can notice several having additional generic argument TLocal
like this:
public static ParallelLoopResult For<TLocal>(
int fromInclusive,
int toExclusive,
Func<TLocal> localInit,
Func<int, ParallelLoopState, TLocal, TLocal> body,
Action<TLocal> localFinally
)
Executes a for loop with thread-local data in which iterations may run in parallel, and the state of the loop can be monitored and manipulated.
换句话说,TLocal
允许您分配、使用和释放一些线程本地状态,即正是您所需要的(TLocal
将是每个线程的 CoefficientVector
个实例).
因此您可以删除 coeff
局部变量并像这样使用上述重载:
CalcPoint[] calcpoints = new CalcPoint[numCalpoints];
Parallel.For(0, numCalpoints,
() => new CoefficientVector { vectors = new Vector[vecSize] }, // localInit
(i, loopState, coeff) => // body
{
coeff.ResetVectors();
//doing some operation on the matrix
for (int n = 0; n < coeff.vectors.Length; n++)
{
coeff.vectors[n].x += n;
coeff.vectors[n].y += n;
coeff.vectors[n].z += n;
}
calcpoints[i].result = coeff.GetResults();
return coeff; // required by the body Func signature
},
coeff => { } // required by the overload, do nothing in this case
);
我正在努力在下面的代码中使用 Parallel.For 而不是 for 循环。 由于 CoefficientVector 向量数组的大小相当大,因此对我来说只重置数组元素值而不是为每次迭代创建新的值是有意义的。
我尝试用Parallel For替换外层循环;并假设并行的每个分区,运行 通过一个单独的线程,将拥有它自己的 CoefficientVector class 副本,因此对我来说有意义(?)每个 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;
}
Parallel.For
方法目前有12个overloads. Besides the variations of int
, long
, ParallelOptions
and ParallelState
action arguments you can notice several having additional generic argument TLocal
like this:
public static ParallelLoopResult For<TLocal>(
int fromInclusive,
int toExclusive,
Func<TLocal> localInit,
Func<int, ParallelLoopState, TLocal, TLocal> body,
Action<TLocal> localFinally
)
Executes a for loop with thread-local data in which iterations may run in parallel, and the state of the loop can be monitored and manipulated.
换句话说,TLocal
允许您分配、使用和释放一些线程本地状态,即正是您所需要的(TLocal
将是每个线程的 CoefficientVector
个实例).
因此您可以删除 coeff
局部变量并像这样使用上述重载:
CalcPoint[] calcpoints = new CalcPoint[numCalpoints];
Parallel.For(0, numCalpoints,
() => new CoefficientVector { vectors = new Vector[vecSize] }, // localInit
(i, loopState, coeff) => // body
{
coeff.ResetVectors();
//doing some operation on the matrix
for (int n = 0; n < coeff.vectors.Length; n++)
{
coeff.vectors[n].x += n;
coeff.vectors[n].y += n;
coeff.vectors[n].z += n;
}
calcpoints[i].result = coeff.GetResults();
return coeff; // required by the body Func signature
},
coeff => { } // required by the overload, do nothing in this case
);