C# 天网基准测试上的TPL示例不是真正的并行?

C# 天网基准测试上的TPL示例不是真正的并行?,c#,.net,parallel-processing,task-parallel-library,C#,.net,Parallel Processing,Task Parallel Library,我发现比较不同语言的并行/分布式处理概念 我查看了.NETTPL基准测试的代码,发现有点奇怪,然后继续调试它 似乎我们有一个任务与主任务并行运行,如果我理解正确的话,我们只对所有同步和递归结果执行异步reduce(聚合) 源代码是: 静态void skynetTplRecursion(ITargetBlock src、long num、long size、long div) { 如果(大小==1) { src.sendsync(num); 返回; } 对于(变量i=0;isum+=VAL.s

我发现比较不同语言的并行/分布式处理概念

我查看了.NETTPL基准测试的代码,发现有点奇怪,然后继续调试它

似乎我们有一个任务与主任务并行运行,如果我理解正确的话,我们只对所有同步和递归结果执行异步reduce(聚合)

源代码是:

静态void skynetTplRecursion(ITargetBlock src、long num、long size、long div)
{
如果(大小==1)
{
src.sendsync(num);
返回;
}
对于(变量i=0;isum+=VAL.sum(),
新的ExecutionDataflowBlockOptions(){MaxDegreeOfParallelism=1,SingleProducerConstrained=true});
LinkTo(actAggregate,newdataflowlinkoptions(){PropagateCompletion=true});
skynetTplRecursion(源、num、大小、div);
source.Complete();
等待完成;
回报金额;
}
我的理解正确吗?若否,原因为何

更新

存储库作者所述的代码目标:

创建一个演员(goroutine,随便什么),产生10个新演员,每个新演员产生10个以上的演员,以此类推,直到在最终关卡上创建100万个演员。然后,它们中的每一个都返回其序号(从0到9999999),这些序号在上一级求和并发送回上游,直到到达根参与者。(答案应该是49999500000)


是的,你说得对。所有递归代码在单个线程上同步运行。还有另一个与之并行运行的计算:对
ActionBlock
中的数组求和


这与代码的描述不太接近。

为什么您希望使用异步。要平行吗?如果没有进一步的保证,您就无法轻松地使此操作并行运行(映射阶段是另一个问题)-在您的情况下,这是可能的(因为
+
当然是有关联的)但是TPL无法从它所基于的委托中看出这一点,因为它希望代码是并行的,因为它正在与基准测试套件中的其他并行实现进行比较。我看了源代码后的理解如问题中所述(不是平行的)。因为我从未见过TPL,我决定在这里问一下我对代码的理解是否正确。你可以让sum并行运行,但TPL无法知道这一点-我猜其他实现以其他方式处理了这一点-如果你能展示其中一个并行运行的代码,也许我可以进一步帮助你?顺便说一句:我真的只是真正了解了它是什么继续详细讨论它的实现方式(使用
和的闭包并对其进行变异是可怕的…这很可能会因为两个线程对其进行操作而中断)在单个线程上聚合是默认框架可以提供给您的-如果您有关联操作的特殊情况,您可以执行
(a*b)*(c*d)
而不是
((a*b)*c)*d
(以及明显的泛化),但是如果操作不是关联的(正如许多操作一样),那么这显然将不起作用。不仅此程序中没有并行计算,而且也没有参与者。@shay_uuuuu数据流块(至少其中一些,如
ActionBlock
)他们和演员很亲近。但这里肯定没有一百万人。
long limit = 1000000;
var x3 = Task.Run( () => skynetTpl( 0, limit, 10 ) );
static void skynetTplRecursion( ITargetBlock<long> src, long num, long size, long div )
{
    if( size == 1 )
    {
        src.SendAsync( num );
        return;
    }

    for( var i = 0; i < div; i++ )
    {
        var sub_num = num + i * ( size / div );
        skynetTplRecursion( src, sub_num, size / div, div );
    }
}

static async Task<long> skynetTpl( long num, long size, long div )
{
    BatchBlock<long> source = new BatchBlock<long>( 1024 );

    long sum = 0;
    ActionBlock<long[]> actAggregate = new ActionBlock<long[]>( vals => sum += vals.Sum(),
        new ExecutionDataflowBlockOptions() { MaxDegreeOfParallelism = 1, SingleProducerConstrained = true } );

    source.LinkTo( actAggregate, new DataflowLinkOptions() { PropagateCompletion = true } );

    skynetTplRecursion( source, num, size, div );
    source.Complete();

    await actAggregate.Completion;

    return sum;
}