有人可以通过代码片段帮助我如何并行处理foreach_in_collection
循环吗?我有大量的收集网/销/单元,我想对其进行遍历。
以串行方式一个接一个地运行需要花费数小时来运行脚本。有没有一种方法可以将我的大列表分成多个部分并让循环并行执行?
理论上,创建一个适当配置的thread pool(因为在处理lots个任务时,线程池比原始线程更易于管理),将所有任务放入池中,然后等待一切完成。复杂的部分是“适当配置”。首先,要创建的线程数量众多(根据经验法则,在调整脚本时,“创建更多的线程,直到总体上无法获得有意义的更好的性能为止),不,要完全自动地完成任务是非常棘手的麻烦”。 >
但是,更重要的是,辅助线程必须能够处理您分配给它们的任务。
如果您的任务受I / O约束,则Tcl中的线程不太可能有很大帮助(因为Tcl实际上非常擅长异步I / O),除非您碰巧做了一个很短的事情之一,其中唯一的API是同步。如果任务受内存限制,那么在获得更多内存之前,线程化是一个坏主意!只有CPU绑定的任务才能真正发挥作用。为了优化这一点,Tcl的实现着重于保持锁的数量非常小,它通过要求您在线程之间复制大多数状态来实现。您可以使用共享变量,但默认情况下不是这样。提供对网络/引脚/单元的操作的代码需要以这种方式可拆分或可感知线程(如果需要,则具有相关的锁)。这是一个主要要求;有效地并行化一个复杂的代码段可能是一个多年的工作!
就是说,理论上,您只是制作了一个本地软件包(在此称为worker
),该软件包提供了每个工作线程的实现,然后执行:]
package require Thread set numThreads 8 set pool [tpool::create -maxworkers $numThreads -initcmd { package require worker }] # Launch the tasks in the background foreach_in_collection item $collection { # worker::processItem is a command you define in the worker package set task [tpool::post -nowait $pool [list \ worker::processItem $item]] set tasks($task) $item lappend inProgress $task } # Wait for them all to complete while {[llength $inProgress]} { foreach finished [tpool::wait $pool $inProgress inProgress] { # Pick up the results from each of the finished tasks set item $tasks($finished) set result [tpool::get $pool $finished] # Not sure what you want to do here puts "$item mapped to $result" } }
原理很容易,但是制作一个有意义的
性能,而不是获得性能。worker
包对您来说真的很难。您不想以一个巨大的全局锁紧紧追随一切而结束。这种方式实际上可以失败