优化并行程序的性能

本文关键字:性能 程序 并行 优化 | 更新日期: 2023-09-27 17:50:15

我用Parallel.For替换了代码中的for循环。性能提升是惊人的(1/3的运行时间)。我尝试使用数组来收集结果代码来解释共享资源。然后我在Parallel.For之外处理数组。这是最有效的方法吗?或者即使没有迭代可以共享相同的循环索引,阻塞仍然会发生吗?CompareExchange的表现会好得多吗?

int[] pageResults = new int[arrCounter];
Parallel.For(0, arrCounter, i =>
{
   AlertToQueueInput input = new AlertToQueueInput();
   input.Message = Messages[i];
   pageResults[i] = scCommunication.AlertToQueue(input).ReturnCode;
});
foreach (int r in pageResults)
{
    if (r != 0 && outputPC.ReturnCode == 0) outputPC.ReturnCode = r;
}

优化并行程序的性能

这取决于您在主循环中是否有任何(有价值的)副作用。

outputPC.ReturnCode是唯一的结果时,可以使用PLINQ:

outputPC.ReturnCode = Messages
    .AsParallel()
    .Select(msg =>    
    {
       AlertToQueueInput input = new AlertToQueueInput();
       input.Message = msg;        
       return scCommunication.AlertToQueue(input).ReturnCode;
    })
    .FirstOrDefault(r => r != 0);

这假设scCommunication.AlertToQueue()是线程安全的,并且您不想在第一个错误之后为剩余的项调用它。

请注意,PLinq中的FirstOrDefault()仅在Framework 4.5及更高版本中有效。

您可以替换:

foreach (int r in pageResults)
{
    if (r != 0 && outputPC.ReturnCode == 0) outputPC.ReturnCode = r;
}

:

foreach (int r in pageResults)
{
    if (r != 0)
    {
        outputPC.ReturnCode = r;
        break;
    }
}

这将在第一次失败时停止循环。

我喜欢David Arno的解决方案,但正如我所看到的,您可以通过将检查放入并行循环中并直接从它中断来提高速度。无论如何,如果任何迭代失败,则将主代码置于失败状态,因此不需要进一步的迭代。

像这样:

Parallel.For(0, arrCounter, (i, loopState) =>
{
   AlertToQueueInput input = new AlertToQueueInput();
   input.Message = Messages[i];
   var code = scCommunication.AlertToQueue(input).ReturnCode;
    if (code != 0)
    {
        outputPC.ReturnCode = code ;
         loopState.Break();
    }
});

乌利希期刊指南1:

如果您需要保存所有迭代的结果,您可以这样做:

int[] pageResults = new int[arrCounter];
Parallel.For(0, arrCounter, (i, loopState) =>
    {
       AlertToQueueInput input = new AlertToQueueInput();
       input.Message = Messages[i];
       var code = scCommunication.AlertToQueue(input).ReturnCode;
       pageResults[i] = code ;
        if (code != 0 && outputPC.ReturnCode == 0)
            outputPC.ReturnCode = code ;    
    });

它将使您免于foreach循环,这是一个改进,尽管是一个小改进。

乌利希期刊指南2:

刚刚发现这篇文章,我认为自定义并行也是一个很好的解决方案。但这是你自己决定是否适合你的任务。