最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

Parallel 类是如何动态调整并行度的?

网站源码admin47浏览0评论
本文介绍了Parallel 类是如何动态调整并行度的?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

限时送ChatGPT账号..

TPL 使用什么反馈来动态调整工作线程的数量?

What feedback does TPL use to dynamically adjust the number of worker threads?

我之前的理解是,它通过衡量任务完成率来查看添加或删除线程是否值得.但是,为什么这段代码会不断增加线程数,即使存在信号量引入的瓶颈?

My previous understanding was that it measures the rate of task completion to see if adding or removing threads is worth it. But then, why does this code keep increasing the number of threads, even though there is a bottleneck introduced by a semaphore?

当然,每秒完成的任务不能超过 20 个,超过 2 个线程不会改善这一点.

Surely, there can be no more than 20 task completions per second, and more than 2 threads will not improve that.

var activeThreads = 0;
var semaphore = new SemaphoreSlim(2);
var res = Parallel.For(0, 1_000_000, i =>
{
    Interlocked.Increment(ref activeThreads);
    semaphore.Wait();
    try
    {
        Thread.Sleep(100);
        Console.WriteLine("Threads: " + activeThreads);
    }
    finally
    {
        Interlocked.Decrement(ref activeThreads);
        semaphore.Release();
    }
});

推荐答案

遇到文章 分析了 2017 年的线程注入算法.截至 2019-08-01,hillclimbing.cpp 文件并没有真正改变,所以文章应该仍然是最新的.

Ran into an article analysing the thread injection algorithm in 2017. As of 2019-08-01, the hillclimbing.cpp file on GitHub hasn't really changed so the article should still be up to date.

相关细节:

.NET 线程池有两种主要的线程注入机制:饥饿避免机制,如果它看到没有,则添加工作线程在排队项目和爬山启发式方面取得了进展尝试在使用尽可能少的线程的同时最大化吞吐量.

The .NET thread pool has two main mechanisms for injecting threads: a starvation-avoidance mechanism that adds worker threads if it sees no progress being made on queued items and a hill-climbing heuristic that tries to maximize throughput while using as few threads as possible.

...

它根据当前"计算所需的线程数吞吐量",即完成的任务数量"(numCompletions)在当前时间段内(以秒为单位的 sampleDuration).

It calculates the desired number of threads based on the ‘current throughput’, which is the ‘# of tasks completed’ (numCompletions) during the current time-period (sampleDuration in seconds).

...

它还把当前线程数(currentThreadCount)带入考虑.

It also takes the current thread count (currentThreadCount) into consideration.

...

真正的.NET Thread Pool只会增加1个线程数每 500 毫秒线程一次.它一直这样做,直到# of线程'已经达到爬山算法的数量建议.

The real .NET Thread Pool only increases the thread-count by one thread every 500 milliseconds. It keeps doing this until the ‘# of threads’ has reached the amount that the hill-climbing algorithm suggests.

...

[hill-climbing] 算法只返回遵守限制的值由 ThreadPool.SetMinThreads(..) 和ThreadPool.SetMaxThreads(..)

The [hill-climbing] algorithm only returns values that respect the limits specified by ThreadPool.SetMinThreads(..) and ThreadPool.SetMaxThreads(..)

...

另外,【爬山算法】只会推荐如果 CPU 利用率低于 95%,则增加线程数

In addition, [the hill-climbing algorithm] will only recommend increasing the thread count if the CPU Utilization is below 95%

所以事实证明线程池确实有基于任务完成率的反馈机制.它也不会明确检查其线程是否被阻塞或正在运行,但它会密切关注整体 CPU 利用率以检测阻塞情况.所有这些也意味着它应该大致了解其他线程和进程在做什么.

So it turns out the thread pool does have a feedback mechanism based on task completion rate. It also doesn't explicitly check whether its threads are blocked or running, but it does keep an eye on overall CPU utilization to detect blockages. All this also means it should be roughly aware of what the other threads and processes are doing.

另一方面,它总是会急切地产生至少与 ThreadPool.SetMinThreads() 所告诉的一样多的线程,默认为机器上的逻辑处理器数量.

On the other hand, it will always eagerly spawn at least as many threads as told by ThreadPool.SetMinThreads(), which defaults to the number of logical processors on the machine.

总而言之,有问题的测试代码做了两件事,使其不断堆积更多线程:

In conclusion, the test code in question was doing two things which make it keep piling up more threads:

有很多任务在排队并排了很长时间,这表明饥饿CPU 利用率可以忽略不计,这意味着新线程应该能够使用它

这篇关于Parallel 类是如何动态调整并行度的?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

发布评论

评论列表(0)

  1. 暂无评论