出于完整性考虑,我在这里搜索并阅读了其他文章,例如:
Parallel.ForEach not spinning up new threads
但是他们似乎没有解决我的问题,所以我们出发:
我有一个数组结构的Parallel.ForEach,像这样:
Dim opts As New ParallelOptions
opts.MaxDegreeOfParallelism = intThreads
Parallel.ForEach(udtExecPlan, opts,
Sub(udtStep)
Dim strItem As String = udtStep.strItem
基本上,对于每个项目,我都会执行一些嵌套循环,最后以这些循环分配作为参数来调用函数。
该函数执行一系列密集的计算(,这会占用该函数的大部分处理时间),并将结果记录在MSSQL表上,如果满足某些条件,该函数将返回True,否则错。如果结果为True,那么我只是从并行函数Sub(udtStep)返回,并且数组中的另一个项应该继续。如果结果为False,则我将简单地遍历最深的嵌套循环的另一次交互,依此类推,努力完成其他外部循环等。因此,简而言之,所有嵌套循环都在主Parallel.ForEach内部循环,就像这样:
Parallel.ForEach(udtExecPlan, opts,
Sub(udtStep)
Dim strItem As String = udtStep.strItem
If Backend.Exists(strItem) Then Return
For intA As Integer = 1 To 5
For intB As Integer = 1 To 50
Dim booResult As Boolean = DoCalcAndDBStuff(strItem, intA, intB)
If booResult = True Then Return
Next intB
Next intA
End Sub)
请务必注意,udtExecPlan具有大约585个元素。每个项目需要1分钟到几个小时才能完成。
现在,这是问题所在:
我是否这样做:
Dim opts As New ParallelOptions
opts.MaxDegreeOfParallelism = intThreads
Parallel.ForEach(udtExecPlan, opts,
其中intThreads是核心计数,或者是我分配给它的任何数字(尝试5、8、62、600),或者我是否只是忽略了整个ParallelOptions声明并从Parallel.ForEach语句中选择,我都注意到了将增加我指定的尽可能多的线程,直至系统中内核的总数(包括HT内核)。很好,一切都很好。
例如,在具有32个核心/ 64个HT核心和128GB RAM的HP DL580G7服务器上,我可以在任务管理器上看到5、8、62或64个线程(使用600选项),这就是我的任务。 d期望。
但是,在处理数组中的项目时,任务管理器上的线程“消失”(从大约75%的利用率变为0%),并且永远不会再旋转,直到只有1个线程在工作。例如,如果我将intThreads设置为62(如果我省略了整个ParallelOptions声明并从Parallel.ForEach语句中选择,则设置为无限),我可以在db表上看到已经处理了62(或64)个项目,但是从那时起上,它一次又回到1个线程和1个项目。
我期望一个项目完成后就可以启动一个新线程,因为大约有585个项目需要处理。几乎是并行完成62或64个项目,然后仅完成一项,直到完成为止,这使得整个服务器此后几乎处于空闲状态。
我想念什么?
我用主Parallel.For循环(没有其他外部循环,如本例所示)尝试了其他一些不同的过程,并获得了相同的行为。
为什么?欢迎任何想法。
我正在将VS.NET 2015与.NET Framework 4.6.1,W2K8R2完全修补。
谢谢!