使用两个处理器组的 C 线程处理
Posted
技术标签:
【中文标题】使用两个处理器组的 C 线程处理【英文标题】:C thread handling with two processor groups 【发布时间】:2020-04-28 11:43:38 【问题描述】:我有一台装有 AMD Threadripper 3990x 的新 PC,它有 64 个内核和 128 个线程。
现在 Windows 10 只能在一个处理器组中处理 64 个内核。所以现在 Windows 制作了两个处理器组。
我编写了创建 N 个进程的软件。我检查如下有多少进程存在:
SYSTEM_INFO sysi;
GetSystemInfo(&sysi);
klas->thread_maxcore = min(sysi.dwNumberOfProcessors, MAX_THREADS);
klas->thread_max = klas->thread_maxcore;
如何调整我的代码以使用所有 128 个线程?使用我当前的代码,我一次只能运行 64 个进程,因此只能使用一个处理器组。
【问题讨论】:
您有什么特定版本/类型的Windows 10
?它们在您的处理器上的表现各不相同。 (正如下面发布的链接中所指出的那样。)
我用w10专业版
考虑使用最近的Linux distribution。他们的 NUMA 支持在您的新 PC 上可能会更好。 C11 或 C++14 中的代码具有更好的平台中立多线程
【参考方案1】:
如何调整我的代码以使用所有 128 个线程
简短的回答是让您的软件了解处理器组,或者强制您的配置只有一个处理器组。
正如您所指出的,Windows 默认情况下,当看到超过 64 个线程时,会将它们分成处理器组。这可能就是您看到的线程数似乎较少的原因。虽然线程数少于您的预期,但它可能仅代表系统总线程数的一部分。
同时多线程有一个设置,默认情况下,在 Windows 10 中,此设置已打开。对于您的 64 核处理器,当启用同时多线程时,系统将显示 128 个线程,但这些线程分为两组。这种默认的 Windows 行为可能是阻止您查看(可见)所有线程的原因。关于您的具体要求我如何调整我的代码以使用所有 128 个线程,
...当程序在组内运行时,除非是处理器 组感知,那么它只能访问同一组中的其他线程...
因此,答案是让您了解软件处理器组,或者通过禁用同时多线程进行设置以将所有内核放入单个处理器组,从而允许您的软件生成所有 128 个线程。 下面的链接中更详细地介绍了这两个选项的方法和权衡...
在此处阅读详细信息...The 64 core Threadripper 3990x CPU Review。
一些可能有助于让您的软件处理器组了解的链接:
C++11 threads, affinity, and hyper-threading
Thread pools and Windows processor groups
摘录改编 C++
上一个链接的代码(由于这个问题被标记为C
,因此将其视为伪代码)
void DistributeThreads(void)
#if OS_WINDOWS_64
//!!BUG!! need to skip this code for old windows versions
int nNumGroups = GetActiveProcessorGroupCount();
if ( nNumGroups > 1 )
Log( "System has %d processor groups", nNumGroups );
for(int i = 0; i < nNumGroups; i++ )
Log(" group %d has %d processors", i, ( int ) GetMaximumProcessorCount( i ) );
int nCurGroup = 0;
int nNumRemaining = GetMaximumProcessorCount( nCurGroup );
for( int i = 0; i < m_threads.size(); i ++ )
auto hndl = m_threads[i].native_handle();
GROUP_AFFINITY oldaffinity;
if ( GetThreadGroupAffinity( hndl, &oldaffinity ) )
//Log( "thread %d, old msk = %x, old grp = %llx", i, oldaffinity.Mask, oldaffinity.Group );
GROUP_AFFINITY affinity;
affinity = oldaffinity;
if ( affinity.Group != nCurGroup )
affinity.Group = nCurGroup;
auto bSucc = SetThreadGroupAffinity( hndl, &affinity, nullptr );
if ( ! bSucc )
Log( "failed to set gr aff err=%x", (int) GetLastError() );
else
//Log( "Set group for thread %d to %d", i, nCurGroup );
--nNumRemaining;
if ( nNumRemaining == 0 )
nCurGroup = min( nCurGroup + 1 , nNumGroups - 1 );
nNumRemaining = GetMaximumProcessorCount( nCurGroup );
#endif
注意:在 MSDN 中搜索函数定义,例如:GetMaximumProcessorCount
【讨论】:
@JohnBollinger - 我已编辑,并相信内容现在与 OP 问题更相关。谢谢。 从未在 c 中使用过处理器组...您可以举个简单的例子吗? @Felix - 你看过链接中的示例代码吗?他们都对解释进行了足够详细的解释,并提供了代码来说明。 :)(请参阅答案中的编辑。)【参考方案2】:该链接指向我的代码和文章。 我刚买了一个 128 核/256 线程和系统,正如你所料,Windows 处理器组意味着大多数程序只使用我的 1/4 内核。 包括visual c++并行STL算法:(。 该代码有效,但省去了所有麻烦,只需使用英特尔 TBB。 当你下载一个适用于 Windows 的线程应用程序并注意到它只使用了你系统的 25% 时,它真的很糟糕。 不要指望 msoft 对此做任何事情。我联系了 Visual c++ 团队,他们都关心我们为这个问题找借口。
【讨论】:
以上是关于使用两个处理器组的 C 线程处理的主要内容,如果未能解决你的问题,请参考以下文章