- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我的内存块可能非常大(大于二级缓存),有时我必须将它们全部设置为零。 memset 在串行代码中很好,但是并行代码呢?如果从并发线程调用 memset 实际上加快了大型数组的速度,有人有经验吗?或者甚至使用简单的 openmp parallel for 循环?
最佳答案
HPC 的人常说一个线程通常不足以使单个内存链接饱和,网络链接通常也是如此。 Here是我为您编写的一个快速而肮脏的启用 OpenMP 的 memsetter,它填充了两次 2 GiB 内存的零。以下是在不同架构上使用具有不同线程数的 GCC 4.7 的结果(报告了多次运行的最大值):
GCC 4.7,使用 -O3 -mtune=native -fopenmp
编译的代码:
四路英特尔至强 X7350 - 带有独立内存 Controller 和前端总线的前 Nehalem 四核 CPU
单 socket
threads 1st touch rewrite
1 1452.223 MB/s 3279.745 MB/s
2 1541.130 MB/s 3227.216 MB/s
3 1502.889 MB/s 3215.992 MB/s
4 1468.931 MB/s 3201.481 MB/s
(第一次接触很慢,因为线程组是从头开始创建的,操作系统正在将物理页面映射到 malloc(3)
保留的虚拟地址空间)
一个线程已经使单个 CPU <-> NB 链接的内存带宽饱和。 (NB = 北桥)
每个套接字1个线程
threads 1st touch rewrite
1 1455.603 MB/s 3273.959 MB/s
2 2824.883 MB/s 5346.416 MB/s
3 3979.515 MB/s 5301.140 MB/s
4 4128.784 MB/s 5296.082 MB/s
需要两个线程来使 NB <-> 内存链接的全部内存带宽饱和。
Octo-socket Intel Xeon X7550 - 具有八核 CPU 的 8 路 NUMA 系统(禁用 CMT)
单 socket
threads 1st touch rewrite
1 1469.897 MB/s 3435.087 MB/s
2 2801.953 MB/s 6527.076 MB/s
3 3805.691 MB/s 9297.412 MB/s
4 4647.067 MB/s 10816.266 MB/s
5 5159.968 MB/s 11220.991 MB/s
6 5330.690 MB/s 11227.760 MB/s
至少需要 5 个线程才能使一个内存链接的带宽饱和。
每个套接字1个线程
threads 1st touch rewrite
1 1460.012 MB/s 3436.950 MB/s
2 2928.678 MB/s 6866.857 MB/s
3 4408.359 MB/s 10301.129 MB/s
4 5859.548 MB/s 13712.755 MB/s
5 7276.209 MB/s 16940.793 MB/s
6 8760.900 MB/s 20252.937 MB/s
带宽几乎与线程数成线性关系。根据单插槽观察,可以说至少需要 40 个线程,每个插槽 5 个线程,才能使所有 8 个内存链接饱和。
NUMA 系统的基本问题是首次接触内存策略 - 内存分配在 NUMA 节点上,其中线程首先接触特定页面内的虚拟地址。线程固定(绑定(bind)到特定的 CPU 内核)对于此类系统至关重要,因为线程迁移会导致远程访问,而远程访问速度较慢。大多数 OpenMP 运行时都支持 pinnig。 GCC 及其 libgomp
具有 GOMP_CPU_AFFINITY
环境变量,Intel 具有 KMP_AFFINITY
环境变量等。另外,OpenMP 4.0 引入了供应商中立的概念地点。
编辑:为了完整起见,以下是在配备 Intel Core i5-2557M(双核 Sandy Bridge)的 MacBook Air 上使用 1 GiB 阵列运行代码的结果带 HT 和 QPI 的 CPU)。编译器是 GCC 4.2.1 (Apple LLVM build)
threads 1st touch rewrite
1 2257.699 MB/s 7659.678 MB/s
2 3282.500 MB/s 8157.528 MB/s
3 4109.371 MB/s 8157.335 MB/s
4 4591.780 MB/s 8141.439 MB/s
为什么即使是单线程也能如此高速?对 gdb
的一点探索表明 memset(buf, 0, len)
被 OS X 编译器翻译成 bzero(buf, len)
并且名为 bzero$VARIANT$sse42
的支持 SSE4.2 的矢量化版本由 libc.dylib
提供并在运行时使用。它使用 MOVDQA
指令一次将 16 个字节的内存清零。这就是为什么即使只有一个线程,内存带宽也几乎饱和。使用 VMOVDQA
的单线程 AVX 启用版本可以一次将 32 个字节归零,并且可能会使内存链接饱和。
这里的重要信息是,有时向量化和多线程在加速操作方面并不正交。
关于c - 在 OpenMP 并行代码中,并行运行 memset 会有什么好处吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11576670/
如果函数定义顺序不对,Jslint 将指出错误。 显然 jslint 是严格的,但我想知道将函数按顺序排列是否有任何好处。 我的意思是在调用它们之前定义它们。 最佳答案 函数定义(和 var 语句)被
关闭。这个问题需要多问focused 。目前不接受答案。 想要改进此问题吗?更新问题,使其仅关注一个问题 editing this post . 已关闭 8 年前。 Improve this ques
我注意到Flask tutorial涉及到点的使用。看起来它只是用于在本地创建一个轮子,这将使服务器上的设置变得更容易,但作为一个网络开发新手,我很好奇:是否有人真的会一路将他们的网站上传到像 PyP
我一直在阅读有关 jquery live event 的内容,但仍然有点困惑?使用它有什么好处? http://docs.jquery.com/Events/live 我知道它与绑定(bind)类似,
这是我的故事:我已将我的应用迁移到 AndroidX,因为我需要从网上找到的库中获取一些新功能。 问题:我目前遇到了一些问题,因为我现在需要为 Cordova 开发一个插件来实现该应用程序的一部分。
在使用 RAD 或一般不使用单元测试时使用依赖注入(inject)是否有任何好处? 最佳答案 是的,有以下几个好处: 减少依赖 减少依赖携带 更多可重用代码 更多可测试代码 更具可读性的代码 更多引用
我目前正在构建一个通过 MSI Windows Installer 分发的产品。我们的客户正在使用不同的形式(例如我们在他们自己的 MSI 中)集成该产品,使用 Bootstrap /链接器(如 Wi
有人声称 Scala 的类型系统是图灵完备的。我的问题是: 这有正式的证据吗? 简单的计算在 Scala 类型系统中会是什么样子? 这对 Scala 这种语言有什么好处吗?与没有图灵完备类型系统的语言
我开始尝试使用 React,我注意到我正在制作的简单应用程序全部使用 JS。我的 html 页面只是一个空的 body 标签! 所以我有几个问题,因为我是这个框架的新手。 我的整个应用程序应该基本上都
我们有一个相当大的基于 Windows 的 1.1 .NET 应用程序,我们正在考虑升级到 2.0。我们考虑更新的主要原因是我们可以利用 Visual Studio 2008 进行项目的持续开发,以及
我有一个页面,其中内置了基于 ajax 的分页。分页用于页面中的“评论”功能。根据 Google 的网站管理员博客,具有 rel="next"和 rel="prev"值有利于 SEO。 我在头部添加了
我是一名优秀的程序员,十分优秀!