在 macOS Apple Silicon 上使用 Homebrew 的 Clang 编译的 C++ 代码在使用 OpenMP 的情况下运行速度明显慢于不使用 OpenMP 的情况

2023-12-20

我正在尝试在 Apple Silicon (Apple M1 Max) 上的 macOS Monterey (12.5.1) 上编译支持 OpenMP 的 C++ 代码,以获得相应的加速。

该代码计算量大,易于理解,多年来一直使用 OpenMP(例如在 x64 Ubuntu 上),没有出现任何问题;计算或多或少是令人尴尬的并行,因此通过 OpenMP 以多线程方式运行计算的速度是显着的。

当我使用 Apple Clang 在 macOS 上编译代码时,一切正常,除了代码当然是单线程运行的,因为 AppleClang 不支持 OpenMP。

这就是为什么我现在使用 Homebrew 的 Clang 编译所有内容以启用 OpenMP。不幸的是,结果与预期不同。代码编译并使用OpenMP;我发现因为我必须解决一些小问题firstprivateClang 比 GCC 更严格的子句,我看到使用多个线程执行。

然而,运行时withOpenMP 是明显慢一些 than withoutOpenMP。例如,不使用 OpenMP 的计算需要大约 15 秒,使用 OpenMP 需要大约 90 秒,即使在最糟糕的扩展情况下,我预计速度会提高 2 倍到 4 倍。否则计算结果是正确的,它似乎只是影响速度。

我尝试使用 llvm 14(稳定 14.0.6(瓶装))和 llvm 13(稳定 13.0.1(瓶装),由于怀疑回归而尝试)编译该软件,但到目前为止没有成功。

该项目正在使用 CMake,配置如下所示(这是使用 LLVM 13,但我事先尝试过使用默认的 llvm):

export PATH="/opt/homebrew/opt/llvm@13/bin:$PATH"
...
cmake ../../ -DCMAKE_BUILD_TYPE=Release  \
  -DCMAKE_PREFIX_PATH=/opt/homebrew/opt/llvm@13   \
  -DCMAKE_CXX_COMPILER=/opt/homebrew/opt/llvm@13/bin/clang++   \
  -DCMAKE_C_COMPILER=/opt/homebrew/opt/llvm@13/bin/clang   \
  -DLDFLAGS="-L/opt/homebrew/opt/llvm@13/lib"   \
  -DCPPFLAGS="-I/opt/homebrew/opt/llvm@13/include"

我很高兴就如何解决此问题提供任何建议。提前致谢!

--

更新1:

当 OMP_DISPLAY_ENV 启用时,将显示以下内容:

OPENMP DISPLAY ENVIRONMENT BEGIN
   _OPENMP='201611'
  [host] OMP_AFFINITY_FORMAT='OMP: pid %P tid %i thread %n bound to OS proc set {%A}'
  [host] OMP_ALLOCATOR='omp_default_mem_alloc'
  [host] OMP_CANCELLATION='FALSE'
  [host] OMP_DEFAULT_DEVICE='0'
  [host] OMP_DISPLAY_AFFINITY='FALSE'
  [host] OMP_DISPLAY_ENV='TRUE'
  [host] OMP_DYNAMIC='FALSE'
  [host] OMP_MAX_ACTIVE_LEVELS='1'
  [host] OMP_MAX_TASK_PRIORITY='0'
  [host] OMP_NESTED: deprecated; max-active-levels-var=1
  [host] OMP_NUM_TEAMS='0'
  [host] OMP_NUM_THREADS: value is not defined
  [host] OMP_PROC_BIND='false'
  [host] OMP_SCHEDULE='static'
  [host] OMP_STACKSIZE='8176k'
  [host] OMP_TARGET_OFFLOAD=DEFAULT
  [host] OMP_TEAMS_THREAD_LIMIT='0'
  [host] OMP_THREAD_LIMIT='2147483647'
  [host] OMP_TOOL='enabled'
  [host] OMP_TOOL_LIBRARIES: value is not defined
  [host] OMP_TOOL_VERBOSE_INIT: value is not defined
  [host] OMP_WAIT_POLICY='PASSIVE'
OPENMP DISPLAY ENVIRONMENT END

一旦我将 OMP_NUM_THREADS 设置为特定数字,我的测试用例就会产生以下运行时间(通过 Boost 的 cpu_timer 获得的时间)。我们可以清楚地看到,代码在单线程(通过 OMP_NUM_THREADS=1 设置)上运行时速度最快,即使它是使用 OpenMP 支持进行编译的。

  • OMP_NUM_THREADS=1:15.85s wall, 30.97s user + 0.56s system = 31.53s CPU (198.9%)
  • OMP_NUM_THREADS=2:28.91s wall, 69.93s user + 0.71s system = 70.64s CPU (244.3%)
  • OMP_NUM_THREADS=4:36.63s wall, 134.07s user + 1.47s system = 135.54s CPU (370.0%)
  • OMP_NUM_THREADS=8:52.18s wall, 267.80s user + 12.35s system = 280.15s CPU (536.9%)
  • OMP_NUM_THREADS=10:52.29s wall, 285.78s user + 10.57s system = 296.35s CPU (566.8%)

更新2:

来自 asitop 的系统负载 (https://github.com/tlkh/asitop https://github.com/tlkh/asitop):

OMP_NUM_THREADS=1 OMP_NUM_THREADS=8
System load from asitop when OMP_NUM_THREADS=1 System load from asitop when OMP_NUM_THREADS=8

None

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在 macOS Apple Silicon 上使用 Homebrew 的 Clang 编译的 C++ 代码在使用 OpenMP 的情况下运行速度明显慢于不使用 OpenMP 的情况 的相关文章

  • 如何使用 C# 中的参数将用户重定向到 paypal

    如果我有像下面这样的简单表格 我可以用它来将用户重定向到 PayPal 以完成付款
  • 没有强命名的代码签名是否会让您的应用程序容易被滥用?

    尝试了解authenticode代码签名和强命名 我是否正确地认为 如果我对引用一些 dll 非强命名 的 exe 进行代码签名 恶意用户就可以替换我的 DLL 并以看似由我签名但正在运行的方式分发应用程序他们的代码 假设这是真的 那么您似
  • 我如何才能等待多个事情

    我正在使用 C 11 和 stl 线程编写一个线程安全队列 WaitAndPop 方法当前如下所示 我希望能够将一些内容传递给 WaitAndPop 来指示调用线程是否已被要求停止 如果 WaitAndPop 等待并返回队列的元素 则应返回
  • 按成员序列化

    我已经实现了template
  • 在结构中使用 typedef 枚举并避免类型混合警告

    我正在使用 C99 我的编译器是 IAR Embedded workbench 但我认为这个问题对于其他一些编译器也有效 我有一个 typedef 枚举 其中包含一些项目 并且我向该新类型的结构添加了一个元素 typedef enum fo
  • 在哪里可以找到列出 SSE 内在函数操作的官方参考资料?

    是否有官方参考列出了 GCC 的 SSE 内部函数的操作 即 头文件中的函数 除了 Intel 的 vol 2 PDF 手册外 还有一个在线内在指南 https www intel com content www us en docs in
  • 查找c中结构元素的偏移量

    struct a struct b int i float j x struct c int k float l y z 谁能解释一下如何找到偏移量int k这样我们就可以找到地址int i Use offsetof 找到从开始处的偏移量z
  • 用于登录 .NET 的堆栈跟踪

    我编写了一个 logger exceptionfactory 模块 它使用 System Diagnostics StackTrace 从调用方法及其声明类型中获取属性 但我注意到 如果我在 Visual Studio 之外以发布模式运行代
  • C++ OpenSSL 导出私钥

    到目前为止 我成功地使用了 SSL 但遇到了令人困惑的障碍 我生成了 RSA 密钥对 之前使用 PEM write bio RSAPrivateKey 来导出它们 然而 手册页声称该格式已经过时 实际上它看起来与通常的 PEM 格式不同 相
  • 使用 Bearer Token 访问 IdentityServer4 上受保护的 API

    我试图寻找此问题的解决方案 但尚未找到正确的搜索文本 我的问题是 如何配置我的 IdentityServer 以便它也可以接受 授权带有 BearerTokens 的 Api 请求 我已经配置并运行了 IdentityServer4 我还在
  • 如何在整个 ASP .NET MVC 应用程序中需要授权

    我创建的应用程序中 除了启用登录的操作之外的每个操作都应该超出未登录用户的限制 我应该添加 Authorize 每个班级标题前的注释 像这儿 namespace WebApplication2 Controllers Authorize p
  • 垃圾收集器是否在单独的进程中运行?

    垃圾收集器是否在单独的进程中启动 例如 如果我们尝试测量某段代码所花费的进程时间 并且在此期间垃圾收集器开始收集 它会在新进程上启动还是在同一进程中启动 它的工作原理如下吗 Code Process 1 gt Garbage Collect
  • 使用 x509 证书签署 json 文档或字符串

    如何使用 x509 证书签署 json 文档或字符串 public static void fund string filePath C Users VIKAS Desktop Data xml Read the file XmlDocum
  • 链接器错误:已定义

    我尝试在 Microsoft Visual Studio 2012 中编译我的 Visual C 项目 使用 MFC 但出现以下错误 error LNK2005 void cdecl operator new unsigned int 2
  • 如何使用 C# / .Net 将文件列表从 AWS S3 下载到我的设备?

    我希望下载存储在 S3 中的多个图像 但目前如果我只能下载一个就足够了 我有对象路径的信息 当我运行以下代码时 出现此错误 遇到错误 消息 读取对象时 访问被拒绝 我首先做一个亚马逊S3客户端基于我的密钥和访问配置的对象连接到服务器 然后创
  • 如何在Xamarin中删除ViewTreeObserver?

    假设我需要获取并设置视图的高度 在 Android 中 众所周知 只有在绘制视图之后才能获取视图高度 如果您使用 Java 有很多答案 最著名的方法之一如下 取自这个答案 https stackoverflow com a 24035591
  • 测试用例执行完成后,无论是否通过,如何将测试用例结果保存在变量中?

    我正在使用 NUNIT 在 Visual Studio 中使用 Selenium WebDriver 测试用例的代码是 我想在执行测试用例后立即在变量中记录测试用例通过或失败的情况 我怎样才能实现这一点 NUnit 假设您使用 NUnit
  • C# 模拟VolumeMute按下

    我得到以下代码来模拟音量静音按键 DllImport coredll dll SetLastError true static extern void keybd event byte bVk byte bScan int dwFlags
  • C++ 中类级 new 删除运算符的线程安全

    我在我的一门课程中重新实现了新 删除运算符 现在我正在使我的代码成为多线程 并想了解这些运算符是否也需要线程安全 我在某处读到 Visual Studio 中默认的 new delete 运算符是线程安全的 但这对于我的类的自定义 new
  • C++ 标准是否指定了编译器的 STL 实现细节?

    在写答案时this https stackoverflow com questions 30909296 can you put a pimpl class inside a vector我遇到了一个有趣的情况 这个问题演示了这样一种情况

随机推荐