如何在并行化后跟踪循环值

时间:2018-02-16 23:52:25

标签: c# parallel-processing

我有一个嵌套的for循环,需要30秒才能运行,我希望根据我机器上的核心数并行化它。

原创循环:

var currentCap = model.LoanCap;
var currentRlRate = model.RlRate;
var maxRateObj = new Dictionary<string, double>();
var maxRateOuterLoopCount = 0;
var maxRateInnerLoopCount = 0;

for (var i = currentRlRate + rlRateStep; i <= maxRlRate; i += rlRateStep)
{
    maxRateOuterLoopCount++;
    var tempFyy = currentFyy;
    var tempIrr = currentIrr;
    var lowestCapSoFar = currentCap;
    var startingCap = maxRateObj.ContainsKey(capKey) ? maxRateObj[capKey] : currentCap;
    for (var j = startingCap - capStep; j >= minCap; j -= capStep)
    {
        maxRateInnerLoopCount++;
        tempModel = new ApplicationModel(model);
        var tempIrrAndFyy = GetIrrAndFyyTuple(tempModel, i, j, precision);
        var updatedIrr = tempIrrAndFyy.Item1;
        var updatedFyy = tempIrrAndFyy.Item2;

        // stop decrementing cap because we got a good-enough IRR to save this pair
        if (Math.Abs(currentIrr - updatedIrr) >= irrDiffPrecision || updatedFyy < minFyy)
        {
            var endingCap = j + capStep; // go back one step since we just stepped out of bounds
            maxRateObj = new Dictionary<string, double>
            {
                {rlRateKey, i },
                {capKey, endingCap }
            };
            // set vars so the outer loop can check if we are still operating within constraints
            lowestCapSoFar = endingCap;
            tempIrr = updatedIrr;
            tempFyy = updatedFyy;
            break;
        }
    }
    // Break out of the outerloop if the cap gets too low
    if (lowestCapSoFar <= minCap) { break; }
    // ... or if Fyy gets too low (when credit policy is enforced)
    if (enforceFyyPolicy && tempFyy < minFyy) { break; }
    // ... or if Irr gets too low (when credit policy is enforced)
    if (enforceIrrPolicy && Math.Abs(tempIrr - targetIrr) > irrDiffPrecision) { break; }
}

现在,当我将此循环移动到Parallel.For()的主体中时,我失去了之前对变量i所具有的上下文...我怎样才能恢复该功能,因为我需要它我的maxRateObj

var degreeOfParallelism = Environment.ProcessorCount;
var result = Parallel.For(0, degreeOfParallelism, x =>
{
    var tempFyy = currentFyy;
    var tempIrr = currentIrr;
    var lowestCapSoFar = currentCap;
    var startingCap = maxRateObj.ContainsKey(capKey) ? maxRateObj[capKey] : currentCap;
    for (var j = startingCap - capStep; j >= minCap; j -= capStep)
    {
        tempModel = new ApplicationModel(model);
        var tempIrrAndFyy = GetIrrAndFyyTuple(tempModel, i, j, precision);  // i IS NOT DEFINED HERE!
        var updatedIrr = tempIrrAndFyy.Item1;
        var updatedFyy = tempIrrAndFyy.Item2;

        // stop decrementing cap because we got a good-enough IRR to save this pair
        if (Math.Abs(currentIrr - updatedIrr) >= irrDiffPrecision || updatedFyy < minFyy)
        {
            var endingCap = j + capStep; // go back one step since we just stepped out of bounds
            maxRateObj = new Dictionary<string, double>
            {
                {rlRateKey, i }, // i IS NOT DEFINED HERE!
                {capKey, endingCap }
            };
            // set vars so the outer loop can check if we are still operating within constraints
            lowestCapSoFar = endingCap;
            tempIrr = updatedIrr;
            tempFyy = updatedFyy;
            break;
        }
    }
    // Break out of the outerloop if the cap gets too low
    if (lowestCapSoFar <= minCap) { return; }
    // ... or if Fyy gets too low (when credit policy is enforced)
    if (enforceFyyPolicy && tempFyy < minFyy) { return; }
    // ... or if Irr gets too low (when credit policy is enforced)
    if (enforceIrrPolicy && Math.Abs(tempIrr - targetIrr) > irrDiffPrecision) { return; }
});

1 个答案:

答案 0 :(得分:1)

不要进行degreeOfParallelism次并行迭代。在您的并行循环中执行与之前相同的迭代次数,但是使用ParallelOptions.MaxDegreeOfParallelism将它们分布在处理器上。

在我看来,这是一个执行从0到numSteps(下面计算)的并行循环,设置循环的MaxDegreeOfParallelism并重构i的问题来自循环体中x的值。有点像...

var start = (currentRlRate + rlRateStep);
var end = maxRlRate;
var numSteps = (end - start) / rlRateStep;
Parallel.For(0, 
    numSteps, 
    new ParallelOptions { 
        MaxDegreeOfParallelism = degreeOfParallelism 
    }, 
    x => {
        var i = (x * rlRateStep) + start;
        //lean on i
    });