C#并行处理选项

C#并行处理选项,c#,multithreading,parallel-processing,threadpool,C#,Multithreading,Parallel Processing,Threadpool,我试图让我的部分代码并行运行,我尝试使用c#中的ThreadPool来避免任何麻烦,但是似乎我对池的要求太高了,我的代码实际上运行得比较慢 下面的代码解释了我要做的事情,我有许多音频样本(取决于512->4096之间的缓冲区大小),需要在延迟网络中插入、传播并从节点(从n=4到n=16)读取。这必须在一个样本一个样本的基础上进行,因此我唯一的优化选择是对网络中存在的每个节点进行插入/传播/读取和并行操作。此操作在每个游戏帧中调用一次,并且在游戏的整个生命周期中都是必需的。查看剖面仪时,散射操作需

我试图让我的部分代码并行运行,我尝试使用c#中的ThreadPool来避免任何麻烦,但是似乎我对池的要求太高了,我的代码实际上运行得比较慢

下面的代码解释了我要做的事情,我有许多音频样本(取决于512->4096之间的缓冲区大小),需要在延迟网络中插入、传播并从节点(从n=4到n=16)读取。这必须在一个样本一个样本的基础上进行,因此我唯一的优化选择是对网络中存在的每个节点进行插入/传播/读取和并行操作。此操作在每个游戏帧中调用一次,并且在游戏的整个生命周期中都是必需的。查看剖面仪时,散射操作需要花费大量时间,因此这是一个很好的选择(我已经做了传统的优化)。目前,我让threadpool worker在一个工作项中为所有节点执行工作,只是为了启动并运行,但工作可以在以后拆分

我认为下面代码的问题是将工作项插入到线程池的频率,我也在某个地方读到过,线程需要一段时间才能启动,因此如果线程池创建更多的工作项,则不一定会有帮助。是否有人对其他并行处理方法有任何建议,或者可以发现我的线程池实现中的任何错误

public void propagateNetwork() {

    int numSampsToConsume = Mathf.min(inSamples.Count,buffersize);

    for (int i = 0; i < numSampsToConsume; i++) {
        outVal = 0.0f;
        inVal = inSamples.Dequeue () * networkInScale;

        directDelay.write (inVal);
        directVal = directDelay.read ();
        directVal *= directAtt;

        for (j = 0; j < network.Count; j++) {
            outVal += network [j].getOutgoing ();
            network [j].inputIncoming (inVal);
        }

        ThreadPool.QueueUserWorkItem (scatteringThreadPoolWrapper);
        scatteringThreadDone.WaitOne ();

        outVal += directVal;
        outSamples.Enqueue (outVal);
    }
}

public void scatteringThreadPoolWrapper(object threadConext) {
    doScatteringForNodeRange (0, network.Count);
}

public void doScatteringForNodeRange(int min,int max) {
    for (int i = min; i < max; i++) {
        network[i].doScattering (doLateReflections);
    }
    scatteringThreadDone.Set ();
}
公共网络(){
int numSampsToConsume=Mathf.min(inSamples.Count,buffersize);
对于(int i=0;i
也许使用
并行。因为
会起作用吗?我将一些变量设置为每个循环迭代的局部变量,但我不知道这些操作都在做什么,以及如果并行运行,会如何导致问题

public void propagateNetwork() {
    int numSampsToConsume = Mathf.min(inSamples.Count,buffersize);

    Parallel.for(0, numSampsToConsume, i => {
        var outVal = 0.0f;
        var inVal = inSamples.Dequeue () * networkInScale;

        directDelay.write (inVal);
        var directVal = directDelay.read ();
        directVal *= directAtt;

        Parallel.for(0, network.Count, j => {
            outVal += network [j].getOutgoing ();
            network [j].inputIncoming (inVal);
        });

        doScatteringForNodeRange (0, network.Count);

        outVal += directVal;
        outSamples.Enqueue (outVal);
    });
}

如果你排队,然后立即等待,这难道不意味着你就不需要这么做了吗?您不应该将所有工作项排队,然后在另一个循环中等待它们完成吗?也许考虑将你的外部替换为<代码>并行。对于< /代码>?也许我误解了线程池所做的事情,但是我假设我分配给它的每一个任务都可能在不同的线程上。因此,总体而言,它将更快地完成?我知道在示例代码中,我还没有将工作分解,这只是一个测试,看看它是否有效。我需要等待,因为每个示例都必须在进入下一个示例之前完成传播,出于同样的原因,不可能进行并行。每个任务可能位于不同的线程上,但是如果您将任务发送到另一个线程,然后在运行另一个任务之前等待在主线程上获得答案,那么您当然会比较慢。您仍然一次只运行一个线程,但是您增加了创建线程和跨线程通信的开销。请确保这是合理的。正如我所说,上面的实现不是真正的并行verison。理想情况下,我会分割要处理的节点,因此发送一半由线程池处理,其余在主线程中处理——等待是为了确保在下一个示例之前完成所有操作。开销的增加让我非常惊讶,分析器中的串行版本的代码显示平均要计算200ms,而并行版本大约是1000ms!您为此尝试过TPL数据流吗?刚刚实现了最内层的并行for,但它仍然比普通的for循环需要更长的时间!与threadpool不同,threadpool试图重用池中尽可能多的线程,并且只在需要时创建线程,是否会为每个i创建新线程?我认为我的主要问题是旋转新线程花费的时间太长(如果这是parallel for所做的),最外层的循环不能是并行的,因为每个样本都必须按顺序传播。速度减慢可能是由于并行操作的嵌套,毕竟在调用时仍然是一个“同步”操作(例如,doScatteringForNodeRange在完成内部循环之前不会运行),这本质上意味着每个外部循环都在管理并行状态,生成其他并行任务并暂停。理想情况下,您希望一个循环完成所有操作,因此:1.查看是否可以将内部循环扩展为主驱动程序;2.避免任何共享状态访问。通过嵌套并行操作,您是指此asnwer中的2个并行for吗?因为正如我之前提到的,我不能将外部for作为并行的,因此没有实现它。所有音频样本都必须按顺序处理,只有内部的操作才是并行的候选。但是你关于交换内部和外部循环的观点很有趣,我会考虑一下这是否可行!我有一个简短的ink关于交换内部/外部环路。在算法的逻辑中,这是不可能的,每个节点在每个时间步(或样本传播)都依赖于来自其他每个节点的输入,因此它们将以这种方式不同步。