如何为每个核心分配2个MPI进程?
例如,如果我这样做,mpirun -np 4 ./application它应该使用2个物理核心来运行4个MPI进程(每个核心2个进程).我正在使用Open MPI 1.6.我做了mpirun -np 4 -nc 2 ./application但是无法运行它.
它抱怨 mpirun was unable to launch the specified application as it could not find an executable:
超线程是否允许使用 L1 缓存在两个线程之间交换数据,这两个线程在单个物理内核上同时执行,但在两个虚拟内核中?
前提是两者都属于同一个进程,即在同一个地址空间中。
第 85 页 (2-55) -英特尔® 64 位和 IA-32 架构优化参考手册:http : //www.intel.com/content/dam/www/public/us/en/documents/manuals/64-ia- 32-architectures-optimization-manual.pdf
2.5.9 英特尔® 微架构代号 Nehalem 中的超线程技术支持
...
更深的缓冲和增强的资源共享/分区策略:
HT 操作的复制资源:寄存器状态、重命名的返回堆栈缓冲区、大页面 ITLB。
HT 操作的分区资源:加载缓冲区、存储缓冲区、重新排序缓冲区、小页面 ITLB 在两个逻辑处理器之间静态分配。
HT 操作期间竞争性共享的资源:保留站、缓存层次结构、填充缓冲区、DTLB0 和 STLB。
HT操作时交替:前端操作一般在两个逻辑处理器之间交替,以保证公平性。
HT 未知资源:执行单元。
我已经阅读了几个关于如何决定线程池大小的问题和文章.问题包括:
文章包括:
在启用了超线程的计算机上,在决定线程池大小时是否应该考虑虚拟内核?
以Brian Goetz在Java Concurrency In Practice一书中提出的建议为例,一般来说,对于一个可以考虑( # of cores + 1 )用作线程数的CPU绑定应用程序.对于具有4个真实内核和8个虚拟(超线程)内核的英特尔酷睿i7芯片,该公式是( 4 + 1 )或者( 8 + 1 )?
此外,应用程序的性质在如何考虑超线程核心方面有多大差异?
与上面提到的相反,我自己的应用程序不受CPU限制.相反,我的应用程序是服务器端Vaadin应用程序,其中线程正在建立Internet连接并通过JDBC访问本地数据库,每分钟几次.鉴于超线程基本上是连接到同一核心的第二组寄存器,也许一个受CPU限制的应用程序应该只考虑真正的核心而网络/ IO绑定的应用程序应该考虑虚拟核心?
最后,英特尔芯片的类型是否会影响超线程,从而影响线程池大小?具体来说,Xeon和Core i7/i5之间的这个问题是否存在差异?例如,当前MacBook(Core i7)和Mac Pro(Xeon)之间的差异.
我意识到涉及许多变量,这是一个复杂的主题.没有完全精确的答案是可能的.我只是在寻找一些通用的规则和建议,以帮助像我这样对这些硬件问题不那么精明的程序员.
我正在开始使用多线程编程,所以如果以下内容显而易见,请原谅.我正在为图像处理程序添加多线程,并且加速并不完全是我期望的.
我目前在具有超线程(4)的4个物理处理器CPU上获得4倍的加速,所以我想知道这种加速是否是预期的.我唯一能想到的是,如果单个物理CPU的两个超线程都必须共享某种内存总线,那么它可能是有意义的.
考虑到所有内存都分配在RAM中(我明白我的操作系统的虚拟内存管理器将决定是否进入页面,因此对于多线程来说,我不完全清楚这是否会被视为I/O绑定程序)这个假设的内存量来自堆)我的机器有16Gb的RAM,以防它决定分页/交换是否是一个问题.
我编写了一个测试程序,展示了使用QThreadPool和tbb :: parallel_for的串行案例和两个并行案例
您可以看到的当前程序除了将假定的图像从黑色设置为白色之外没有任何实际操作,并且它是为了在将任何实际操作应用于图像之前知道基线是什么而完成的.
我正在附加该程序,希望有人可以解释我,如果我在这种处理算法中寻求大约8倍的加速是一个失败的原因.请注意,我对其他类型的优化(例如SIMD)不感兴趣,因为我真正关心的不仅仅是让它更快,而是使用纯多线程使其更快,而不需要进入SSE或处理器缓存级别优化.
#include <iostream>
#include <sys/time.h>
#include <vector>
#include <QThreadPool>
#include "/usr/local/include/tbb/tbb.h"
#define LOG(x) (std::cout << x << std::endl)
struct col4
{
unsigned char r, g, b, a;
};
class QTileTask : public QRunnable
{
public:
void run()
{
for(uint32_t y = m_yStart; y < m_yEnd; y++)
{
int rowStart = y * m_width;
for(uint32_t x = m_xStart; x < m_xEnd; x++)
{
int index = rowStart + x;
m_pData[index].r = 255;
m_pData[index].g = …Run Code Online (Sandbox Code Playgroud) 在g ++ 4.7中的OpenMP(并行使用)效率不是很高吗?在使用5倍CPU的情况下为2.5倍,我确定程序的性能在使用默认值的情况下在500%CPU左右的11s和13s之间变化(通常总是高于12s,有时甚至慢于13.4s)#pragma omp parallel for,并且OpenMP加速仅为在g++-4.7 -O3 -fopenmp4核8线程Xeon上,在5倍CPU w /时为2.5倍。
我尝试使用schedule(static) num_threads(4),并注意到我的程序始终在大约320%的CPU上以11.5s至11.7s(总是低于12s)完成操作,例如,运行更一致,并且使用了更少的资源(即使最好的运行速度比运行速度慢了半秒)具有超线程的罕见异常值)。
是否有任何简单的OpenMP方式可检测超线程并减少num_threads()到CPU内核的实际数量?
(有一个类似的问题,由于使用OpenMP的超线程导致的性能不佳:如何将线程绑定到内核,但是在我的测试中,我发现仅将线程从8个减少到4个就已经可以用g ++-4.7做到这一点。在Debian 7 Wheezy和Xeon E3-1240v3上,因此,这个问题仅仅是关于减少num_threads()内核数。)
我正在做一些基准测试,并希望禁用 EC2 中的超线程以查看它对我的测试应用程序性能的影响。
我的应用程序的单个实例在执行期间仅使用 1 个线程。
据我了解,我无法访问 EC2 计算机的 BIOS 来禁用超线程,因为它们都是虚拟化的。但我使用该chcpu命令禁用了一半可用的 vCPU(线程),以便我可以模拟禁用超线程的环境。
对于此基准测试,我使用带有 4 个 vCPU 的 C4.xlarge,逻辑编号为 0 到 3。
我运行此命令sudo chcpu -d 1,3禁用 vCPU 1 和 3。
在此过程中,我假设 vCPU 0 和 1 来自单个底层裸机核心,vCPU 2 和 3 来自另一个核心。
我知道我的假设是错误的,因为 vCPU 0 和 4 可能来自同一个裸机核心,也可能全部来自不同的裸机核心。
有没有人有更好的方法来禁用 EC2 实例中的超线程?
当亚马逊检测到一半的 vCPU 被禁用时,是否会重新排列 vCPU,使它们来自不同的内核?
想象一下,我想让一个主线程和一个辅助线程作为两个超线程在同一物理核心上运行(可能通过强制它们的亲和力来大致确保这一点)。
主线程将执行重要的高 IPC、CPU 密集型工作。除了定期更新主线程将定期读取的共享时间戳值之外,辅助线程不应该执行任何操作。更新频率是可配置的,但可以快至 100 MHz 或更高。如此快速的更新或多或少排除了基于睡眠的方法,因为阻塞睡眠太慢,无法在 10 纳秒 (100 MHz) 周期内睡眠/唤醒。
所以我想要忙碌的等待。然而,繁忙等待应该对主线程尽可能友好:使用尽可能少的执行资源,从而给主线程增加尽可能少的开销。
我想这个想法将是一个长延迟指令,不使用很多资源,就像pause并且也有一个固定且已知的延迟。这将使我们能够校准“睡眠”周期,因此甚至不需要读取时钟(如果想要更新周期,P我们只需发出P/L这些指令以进行校准的忙睡眠。但pause不满足后一个标准,因为它的延迟各不相同很多1 .
第二种选择是使用长延迟指令,即使延迟未知,并且在每条指令之后执行一个rdtsc或一些其他时钟读取方法(clock_gettime等)来查看我们实际睡了多长时间。看起来它可能会大大减慢主线程的速度。
还有更好的选择吗?
1还有pause一些关于防止推测性内存访问的特定语义,这可能有利于也可能没有利于这个同级线程场景,因为我实际上并不处于自旋等待循环中。
想象一个超标量(多个执行单元)并且还具有超线程 (SMT) 支持的 CPU(或内核)。
为什么 CPU 真正可以并行执行的软件线程数通常由它拥有的逻辑内核(即所谓的硬件线程)数决定,而不是它拥有的执行单元总数?
如果我的理解是正确的,SMT 实际上并没有实现真正的并行执行,它只是通过复制 CPU 的某些部分(那些存储架构状态,但不是主要执行资源的部分)来使上下文切换更快/更有效。另一方面,超标量架构允许每个时钟周期真正同时执行多条指令,因为 CPU 具有多个执行单元,即多个并行流水线,每个流水线都可以以真正的并行方式处理单独的线程。
那么举个例子,如果一个CPU有2个内核,每个内核有2个执行单元,那么它的硬件并发(真正可以并行执行的线程数)不应该是4吗?为什么它的硬件并发性而不是由逻辑内核的数量给出,而 SMT 实际上并没有启用真正的并行执行?
我有许多使用 OpenJDK 11 的 Java 进程在 Windows Server 2019 上运行。该服务器有两个物理处理器和 36 个总内核;这是一台惠普机器。当我启动我的流程时,我会在任务管理器中看到所有内核的工作分配。这很好。然而,在进程运行一段时间后,不是一致的时间量,机器开始只使用一半的内核。
我正在研究一些理论:
JDK 存在一些问题,阻止它始终如一地访问所有内核。
Windows Server 2019 出现问题,限制 Java 访问所有内核。
存在热管理问题,一个处理器变得太热,操作系统将所有处理工作转移到另一个处理器。
超线程和“逻辑”处理器存在一些问题,导致进程无法利用所有内核。
我试过搜索 JDK 问题,但没有找到类似的内容。我去了服务器,虽然它运行起来有点热,但看起来并没有过热。我还没有尝试禁用超线程。我已经尝试了许多参数来强制 JVM 使用所有内核,实际上该进程最初确实使用了所有内核;我可以在任务管理器中看到活动。
有人有什么想法吗?这是一个非常令人困惑的问题,我很感激任何想法。
更新:通过使用任务管理器将 java.exe 进程之一分配给另一个处理器,我能够使其使用另一个处理器。这也适用于命令行上的 java 调用以及使用哪个套接字的参数。
话虽如此,这感觉就像一个黑客。我不明白为什么我必须手动为每个 java 进程分配一个套接字;该工作应该留给操作系统。我仍然不确定问题到底出在哪里,是操作系统还是什么。
我想检测实际物理核心的数量,而不是逻辑核心的数量,当更多线程竞争私有每核心缓存时负扩展的工作负载,和/或具有足够高的 IPC,每个核心运行一个以上的逻辑线程不会通过增加线程开销来增加吞吐量,特别是对于不能完美扩展到大量内核的问题。
或者换句话说,可以运行的线程数,除了内存带宽之外,它们中的任何一个都不会相互竞争执行资源。(编者注:超线程的一些替代方案,例如 AMD Bulldozer 系列 CMP有 2 个整数内核共享一个 FPU/SIMD 单元;您可能希望根据工作负载将其计为 2 个真实内核,即使您不想计算2 个逻辑内核与SMT(例如 Intel 的超线程)共享一个物理内核。)
我知道以前有人问过类似的问题,但答案看起来已经过时了。或者获取物理处理器数量 .NET Core 2.2没有答案,问题中的代码不是完全可移植的。
System.Environment.ProcessorCount仅返回逻辑核心数,因此是我的超线程系统中的两倍。对于一些密集的并行计算,启动线程数不超过可用物理内核数是最有效的- 至少我的测试表明,当我启动更多线程时,性能会显着下降。
我发现一些 Windows 解决方案调用 WMI 或 kernel.dll 来获取物理内核的数量。但是如何在 .net core 上保持平台独立性?是否有隐藏的核心数或可靠的计算方法?
到目前为止,我发现的最有前途的想法是在一个线程上做一些更长的计算并测量它的时间。然后并行执行相同的计算(ae ProcessorCount 线程)并测量总时间。比较两次以猜测物理内核的数量。这可能有效,但对我来说看起来成本高昂且不可靠。
hyperthreading ×10
c++ ×2
cpu ×2
java ×2
performance ×2
x86 ×2
.net ×1
.net-core ×1
affinity ×1
amazon-ec2 ×1
benchmarking ×1
concurrency ×1
cpu-cores ×1
g++-4.7 ×1
openmp ×1
openmpi ×1
smt ×1
superscalar ×1
tbb ×1
threadpool ×1
x86-64 ×1