这可能是一个有点基本的问题(我不得不承认,我对并行编程不是很有经验)。
我编写了一个单线程 C# 程序,在该程序中p
创建了一个参数数组,然后p[i]
用一个函数评估每个参数,然后将每个评估f
对( p[i], f( p[i] ) )
放入一个堆中(按函数值排序)。非常粗略,它看起来像这样:
class Agent {
private double[] parameter;
private double value;
public Agent( double[] par, double val ) { this.parameter = par; this.val = value; }
}
class Work {
public void optimise() {
// return an array of parameters, each one of which is a double array itself
double[][] parameter = getParameters();
Agent[] results = new Agent[ parameter.Length ];
for ( int idx = 0; idx < parameter.Length; idx++ )
results[ idx ] = new Agent( parameter[idx], cost_function( parameter[ idx ] ) );
}
private double cost_function( double[] par ) {
// evaluate par, get result
return result;
}
}
由于评估cost_function
相当冗长,而且parameter
很长,我考虑将其并行化,将 的内容parameter
分成段,然后Parallel.For
在每个段上使用。相当天真地,我将常规更改optimise
为:
public void optimise() {
// select an appropriate number of threads, e.g.
int number_of_threads = Environment.ProcessorCount;
// return an array of parameters, each one of which is a double array itself
double[][] parameter = getParameters();
// split the array of parameters into #number_of_threads many
// segments (of roughly equal size)
double[][][] par_segments = distribute_parameter( parameter );
Agent[][] results = new Agent[ number_of_threads ];
// process each segment in an individual thread
Parallel.For( 0, number_of_threads, idx => {
results[ idx ] = new Agent[ par_segments[ idx ].Length ];
for ( int agent = 0; agent < par_segments[ idx ].Length; agent++ )
results[ idx ][ agent ] =
new Agent( par_segments[ idx ][ agent ], cost_function( par_segments[ idx ][ agent ] );
} );
}
我天真的期望是,对于每个段(即 each idx
),内部的处理将被一致地处理,特别是在创建 eachnew Agent( p, cost_function( p ) )
时,该表达式中的两个p
将是相同的,并且结果Agent
确实包含一个对应的参数和函数值对。但我得到的是new Agent( p1, cost_function( p2 ) )
,而且我什至认为不一定p2
是原始parameter
数组的一部分。
如果我将最后一条语句锁定在该例程中,则该Parallel.For
例程可以正常工作,但这当然会使并行化变得无用。有没有更好的方法来确保结果矩阵将填充一致的参数/值对,而不需要更改原始cost_function
例程?
如果是这样,是否有一个很好的在线资源可以解释这一点?最后一个问题:关于该主题的好书是什么?
提前致谢!最好的,罗伯