You can use a custom partitioner to get the behavior you want without having to resort to using Parallel.Invoke
. The RangPartitioner
is what you want to start with.
var rangePartitioner = Partitioner.Create(0, rawData.Length);
double[] results = new double[rawData.Length];
Parallel.ForEach(rangePartitioner, (range, loopState) =>
{
for (int i = range.Item1; i < range.Item2; i++)
{
scaledData[i] = rawData[i] * scale * offset;
}
});
You can create a custom partitioner and overload the GetPartition()
method to adjust the block size to something that suites your needs.
See Custom Partitioners for PLINQ and TPL for an in depth discussion.
Will this improve data locality, yes. Provided that your array contains value types. In which case they will be allocated as blocks of contiguous memory. For reference types this is not the case. FWIW I've tried to improve memory locality like this with OK but not astounding improvements. I came to the conclusion that there is potentially a lot of other memory access from the CLR and that this can make it hard to understand the resulting memory access patterns.