gpt4 book ai didi

c++ - `NumberOfConcurrentThreads`中参数 `CreateIoCompletionPort`如何使用

转载 作者:可可西里 更新时间:2023-11-01 09:51:44 25 4
gpt4 key购买 nike

查看 MSDN documentation对于 CreateIoCompletionPort 我们读到:

NumberOfConcurrentThreads [in]

The maximum number of threads that the operating system can allow to concurrently process I/O completion packets for the I/O completion port. This parameter is ignored if the ExistingCompletionPort parameter is not NULL.

If this parameter is zero, the system allows as many concurrently running threads as there are processors in the system.

但是,我找到的文档没有说明 IoCompletionPort 实际上创建任何线程。

事实上,example Microsoft 提供使用以下代码来确定有多少处理核心可用(而不是为 NumberOfConcurrentThreads 传递 0),然后实际创建那么多线程。

// The general value of the thread count is the system's processor count.
SYSTEM_INFO sysInfo = { 0 };
GetNativeSystemInfo(&sysInfo);
const DWORD dwThreadCount = sysInfo.dwNumberOfProcessors;

// A class in the example that wraps around IoCompletionPort
IOCompletionPort port;

// Construct the thread pool
HANDLE* hThreads = new HANDLE[dwThreadCount];
for (DWORD i = 0; i < dwThreadCount; ++i) {
// The threads run CompletionThread
hThreads[i] = CreateThread(0, 0, IOCompletionThread, &port, 0, NULL);
}

在我看来,这似乎表明以某种方式存在与 IoCompletionPort 关联的“承载能力”。但这是如何表现出来的呢?我很难理解如何(甚至为什么需要这样做)有权访问完成端口的线程会被阻止从完成端口出队。

事实上,我尝试将创建线程的行修改为 new HANDLE[++dwThreadCount](并从声明中删除 const 说明符)和示例似乎毫无怨言地执行。我刚刚在执行结束时注意到一个额外的超时错误。

我目前唯一的结论是 NumberOfConcurrentThreads 是一个没有实际用途的“虚拟”变量,所以我错过了什么?

最佳答案

I/O 完成端口本身不创建线程。 NumberOfConcurrentThreads 参数指定允许多少线程同时并行处理完成数据包。这在另一个 MSDN 页面上有更详细的解释:

I/O Completion Ports

How I/O Completion Ports Work

...

Although any number of threads can call GetQueuedCompletionStatus for a specified I/O completion port, when a specified thread calls GetQueuedCompletionStatus the first time, it becomes associated with the specified I/O completion port until one of three things occurs: The thread exits, specifies a different I/O completion port, or closes the I/O completion port. In other words, a single thread can be associated with, at most, one I/O completion port.

When a completion packet is queued to an I/O completion port, the system first checks how many threads associated with that port are running. If the number of threads running is less than the concurrency value (discussed in the next section), one of the waiting threads (the most recent one) is allowed to process the completion packet. When a running thread completes its processing, it typically calls GetQueuedCompletionStatus again, at which point it either returns with the next completion packet or waits if the queue is empty.

...

Threads and Concurrency

The most important property of an I/O completion port to consider carefully is the concurrency value. The concurrency value of a completion port is specified when it is created with CreateIoCompletionPort via the NumberOfConcurrentThreads parameter. This value limits the number of runnable threads associated with the completion port. When the total number of runnable threads associated with the completion port reaches the concurrency value, the system blocks the execution of any subsequent threads associated with that completion port until the number of runnable threads drops below the concurrency value.

The most efficient scenario occurs when there are completion packets waiting in the queue, but no waits can be satisfied because the port has reached its concurrency limit. Consider what happens with a concurrency value of one and multiple threads waiting in the GetQueuedCompletionStatus function call. In this case, if the queue always has completion packets waiting, when the running thread calls GetQueuedCompletionStatus, it will not block execution because, as mentioned earlier, the thread queue is LIFO. Instead, this thread will immediately pick up the next queued completion packet. No thread context switches will occur, because the running thread is continually picking up completion packets and the other threads are unable to run.

...

The best overall maximum value to pick for the concurrency value is the number of CPUs on the computer. If your transaction required a lengthy computation, a larger concurrency value will allow more threads to run. Each completion packet may take longer to finish, but more completion packets will be processed at the same time. You can experiment with the concurrency value in conjunction with profiling tools to achieve the best effect for your application.

The system also allows a thread waiting in GetQueuedCompletionStatus to process a completion packet if another running thread associated with the same I/O completion port enters a wait state for other reasons, for example the SuspendThread function. When the thread in the wait state begins running again, there may be a brief period when the number of active threads exceeds the concurrency value. However, the system quickly reduces this number by not allowing any new active threads until the number of active threads falls below the concurrency value. This is one reason to have your application create more threads in its thread pool than the concurrency value. Thread pool management is beyond the scope of this topic, but a good rule of thumb is to have a minimum of twice as many threads in the thread pool as there are processors on the system. For additional information about thread pooling, see Thread Pools.

关于c++ - `NumberOfConcurrentThreads`中参数 `CreateIoCompletionPort`如何使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38133870/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com