【发布时间】:2017-06-01 21:26:44
【问题描述】:
我试图让我的一部分代码并行运行,我试图在 c# 中使用 ThreadPool 以避免任何头痛,但似乎我对池的要求太多了,我的代码实际上运行速度较慢它!
下面的代码解释了我想要做什么,我有许多音频样本(取决于从 512->4096 的任何地方的缓冲区大小)需要插入、传播并从节点读取(从 n = 4 到 n = 16) 在延迟网络中。这必须在逐个样本的基础上发生,所以我唯一的优化选择是参与插入/传播/读取的部分,并对网络中存在的每个节点进行并行操作。此操作在每个游戏帧中调用一次,并且在游戏的整个生命周期中都是必需的。查看分析器,散射操作需要大量时间,因此它是一个很好的候选者(我已经完成了传统优化)。目前,我让线程池工作者在一个工作项中为所有节点执行工作,只是为了启动和运行,但可以稍后拆分工作。
我认为下面代码的问题是工作项插入线程池的频率,我还在某处读到线程需要一段时间才能启动,所以如果线程池创建更多,它不一定有帮助。是否有人对其他并行处理方法有任何建议,或者可以发现我的线程池实现的任何错误?
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 ();
}
【问题讨论】:
-
如果你排队然后立即等待,那不是没有意义吗?您不应该将所有工作项排队,然后等待它们在另一个循环中完成吗?也许考虑用
Parallel.for替换你的外部? -
也许我误解了线程池的作用,但我假设我分配给它的每个任务都可能在不同的线程上。因此总的来说它会更快完成吗?我知道在示例代码中我还没有拆分工作,这只是一个测试,看看它是否有效。我需要等待,因为每个样本都必须在移动到下一个之前完成传播,出于同样的原因,并行 for 是不可能的。
-
每个任务可能在不同的线程上,但是如果你将一个任务发送到另一个线程,然后在运行另一个任务之前等待在主线程上得到答案,那么你当然会变慢。您仍然一次只运行一个线程,但增加了创建线程和跨线程通信的开销。
-
当然有道理。就像我说的,上面的实现并不是真正的并行版本。理想情况下,我会拆分要处理的节点,因此发送一半由线程池处理,其余在主线程中处理 - 等待以确保在下一个示例之前完成所有操作。开销的增加对我来说非常令人惊讶,分析器中代码的串行版本显示平均计算时间为 200 毫秒,而并行版本约为 1000 毫秒!
-
您为此尝试过 TPL 数据流吗?
标签: c# multithreading parallel-processing threadpool