问题标签 [memory-bandwidth]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
1 回答
530 浏览

c++ - OpenMP 和内存带宽限制

编辑:我的第一个代码示例是错误的。用更简单的固定。

我为大型向量和矩阵之间的代数运算实现了一个 C++ 库。我发现在 x86-x64 CPU 上,OpenMP 并行向量加法、点积等并不比单线程快。并行操作比单线程快 -1% - 6%。这是因为内存带宽限制(我认为)。

所以,问题是,这样的代码是否有真正的性能优势:

在此示例中,使用 OpenMP 没有严重的缺陷。但是,如果我正在使用稀疏向量和稀疏矩阵处理 OpenMP,例如,我不能使用 *.push_back(),在这种情况下,问题变得很严重。(稀疏向量的元素不像密集向量那样连续,因此并行编程有一个缺点,因为结果元素可以随时到达 - 而不是从低到高的索引)

0 投票
1 回答
3078 浏览

performance - 单核可实现的内存带宽

在现代多核平台上,内存带宽受限应用程序的并行性能通常不能很好地随内核数量而扩展。通常,在达到一定数量的内核时会观察到加速,但在那之后性能就会饱和。一个综合的例子是著名的STREAM 基准测试,它通常用于报告可实现的内存带宽,即饱和点的内存带宽。

考虑在峰值内存带宽为 42.7GB/s (DDR3-1333) 的单个 Xeon E5-2680 上的 STREAM 基准测试 (Triad) 的以下结果:

STREAM 可以很好地从 1 核扩展到 2 核,但在 3 核以上时,性能大致保持不变。

我的问题是:是什么决定了单个 CPU 内核可以实现的内存带宽?由于这个问题太宽泛了,我把它缩小到上面提到的架构:我怎么能预测带有 1 个线程的 STREAM 会给我 16 GB/s 从 E5-2680 的规格,或者通过查看硬件计数器等?

0 投票
2 回答
4939 浏览

optimization - 为什么memset慢?

我的 CPU 规格说它应该获得 5.336GB/s 的内存带宽。为了测试这一点,我编写了一个简单的程序,它在一个大数组上运行 memset(或 memcpy)并报告时间。我在 memset 上显示 3.8GB/s,在 memcpy 上显示 1.9GB/s。 http://en.wikipedia.org/wiki/Intel_Core_(microarchitecture)说我的 Q9400 应该达到 5.336MB/s。怎么了?

我尝试用赋值循环替换 memset 或 memcpy。我已经四处搜索以尝试了解内存对齐。我尝试了不同的编译器标志。我为此花费了令人尴尬的几个小时。感谢您的任何帮助,您可以提供!

我正在使用带有 libc-dev 版本 2.15-0ubuntu10.5 和内核 3.8.0-37-generic 的 Ubuntu 12.04

编码:

编译命令:

示例输出:

根据 lshw 我的硬件:

0 投票
1 回答
110 浏览

performance - CUDA 块大小 1024x1 与 32x32 会有任何性能差异吗?

从线程调度和内存带宽的角度来看,这两种块大小(1024x1 与 32x32)如何执行?这两种块大小的性能是否有任何预期差异?请注意,每个块都使用 1024 个线程。

0 投票
1 回答
250 浏览

cuda - CUDA 带宽测试以获得可达到的峰值

我想知道我的 CUDA 内核在内存带宽利用率方面有多好。我在开启 ECC 的 Tesla K40c 上运行它们。实用程序给出的结果是否bandwidthTest很好地近似于可达到的峰值?否则,如何编写类似的测试来找到峰值带宽?

我的意思是设备内存带宽。

0 投票
1 回答
2210 浏览

performance - 在CUDA中,为什么cudaMemcpy2D和cudaMallocPitch会消耗大量时间

正如标题中提到的,我发现函数cudaMallocPitch()消耗大量时间,也cudaMemcpy2D()消耗相当多的时间。

这是我正在使用的代码:

实现时Size.widthSize.height都是4800,耗时cudaMallocPitch()约150-160ms(以防万一多次测试),cudaMemcpy2D()耗时约50ms。

CPU和GPU之间的内存带宽似乎不可能如此有限,但是我看不到代码中的任何错误,那是什么原因呢?

顺便说一句,我使用的硬件是 Intel I7-4770K CPU 和 Nvidia Geforce GTX 780(相当不错的硬件,没有错误)。

0 投票
1 回答
99 浏览

c - 使用优化的内存带宽方法时我没有看到性能提升

我看到了一个循环的示例,该循环应该比之后的循环慢:

与此相比:

现在,我编写了一个工具来测试不同索引号的数量,但是在我尝试了这个概念之后,我并没有看到太多的性能优势,而且我担心我的代码与它有关......

应该是在我的代码中工作的较慢循环:

应该是“显着”更快的代码:

数据对比:

在此处输入图像描述

0 投票
1 回答
744 浏览

performance - 如何使用 Intel Turbo Boost 修改多核处理器的 STREAM 基准 (MPI)?

我想在集群的一个节点上运行STREAM 基准测试的MPI 版本,以测量不同 MPI 进程数量的可持续带宽。每个节点由两个英特尔® 至强® 处理器 E5-2680 v3(12 核)组成。

在下文中,我将使用openmpi v. 1.8.2 和选项map-by core. 源代码是使用包装器编译的

使用编译器选项

每个核心一直使用长度为 2*10^6 的双精度数组,测试重复 50 次:

令我困惑的是 2-6 个进程的测量可持续带宽停滞不前。我认为使用过的处理器的 Turbo Boost 可能会影响结果。显然 Turbo Boost 仅在使用几个内核时才会激活,但我不确定如何正确解释结果。

要“关闭” Turbo Boost,一种可能是修改 STREAM 基准,如下所示:

  • 始终使用所有 24 个可用内核以在整个基准测试过程中保持处理器负载大致恒定
  • 将基准测试的 MPI 通信器拆分MPI_COMM_WORLD为两个独立的通信器。一个通信器将与实际运行基准测试的N个进程组相关联,另一组包含剩余的24-N 个进程,这些进程仅用于保持内核繁忙并防止 Turbo Boost
  • 24-N进程仅使用 L1 缓存中的数据,以尽量减少对其他进程的影响
  • 将基准测试的运行时间延长到几分钟(Turbo Boost 效果持续时间不超过几秒钟?)

第一个实现仅使用三元组内核来处理应该适合 L1 缓存 (32kByte) 的数据集上的剩余24-N 个进程。Benchmark的重复次数提升至5000,数据数组长度大小提升至1*10^7。调用该函数foo以防止(成功?)循环展开,前面的 if 条件false贯穿整个程序执行。相关代码读取

a、b 和 c 被声明为static double a[LEN],b[LEN],c[LEN]main 之外。我还阅读有关静态修饰符及其对基准测试的影响的讨论。我不确定是否foo真的需要打电话。

不幸的是,我的方法并没有导致与基准测试不同的结果。

我的方法有什么问题?您是否了解替代方案,或者您对我应该如何修改我的基准有建议?


编辑:

由于一位用户对我用于基准测试的代码表现出兴趣:

我使用了 PETSc 附带的 STREAM 基准测试的修改版本:

http://www.mcs.anl.gov/petsc/

在系统上安装 PETSc 后,您会在src/benchmarks/streams

如果你只对源代码感兴趣,你会在他们的 GitHub 页面上找到最新版本:

https://github.com/petsc/petsc/tree/master/src/benchmarks/streams

0 投票
0 回答
128 浏览

x86 - 使用 MOVDQU 实现的复制循环显示了较大的运行间差异

我正在寻求解释我在循环中看到的结果,该循环使用 x86 movdqu 指令从某个源内存位置移动 64 字节到某个目标内存位置(movdqu 指令支持将 16 字节数据从/移到 xmm-寄存器到/从未对齐的内存位置)。这是实现类似于 memcpy()/java.lang.System.arraycopy() 的函数的代码的一部分

我尝试使用两种不同的模式来实现副本:

模式1

在此模式中,rsi 保存源(src)地址,rdi 保存目标(dst)地址,xmm 寄存器用作临时寄存器。此代码的迭代次数与 copylen_in_bytes/64 一样多。如您所见,这里遵循 ld-ld-st-st-ld-ld-st-st 加载存储模式。

模式2

在模式 2 中,遵循 ld-st-ld-st-ld-st-ld-st 模式。

观察

在运行此代码几百次时,其中 src 和 dst 在不同的 8 字节边界处对齐,我观察到以下内容:

在 Westmere (至强 X5690)

Pattern1 表现出非常高的运行间差异。

Pattern2 几乎没有变化。

Pattern2 上的最小时间(最快观察时间)比 Pattern1 上的最小时间高(约 8%)。

在 Ivybridge (Xean E5-2697 v2)

Pattern1 表现出非常高的运行间差异。

Pattern2 几乎没有变化。

Pattern2 的最小时间比 Pattern1 的最小时间高(~20%)。

哈斯韦尔(酷睿 i7-4770)

Pattern1 没有表现出非常高的运行间差异。

Pattern2 几乎没有变化。

Pattern2 的最小时间比 Pattern1 的最小时间高(~20%)。

奇怪的是,在 Westmere 和 Ivybridge 上,src/dest 的对齐与不良结果(导致高方差)之间似乎没有相关性。我看到相同 src/dest 对齐的好坏数字。

问题

我知道跨越缓存行的 movdqu 会比不跨越缓存行的 movdqu 执行得更差,但我不明白以下内容:

1) 为什么 Pattern1 在 Westmere 和 Ivybridge 上表现出高方差?加载存储的顺序有何不同?

2) 为什么 Pattern2 上的最小时间比 Pattern1 慢,跨不同的架构?

感谢您花时间阅读这篇长文。

卡尔提克

0 投票
1 回答
186 浏览

database - SDRAM 双向性——“官方”带宽数据中的读写计数是否相同?

SDRAM 是否能够同时加载和存储?

如果是这样,同时存储和加载如何影响带宽?

  • 总带宽,作为存储和加载带宽的总和,在两者都做时会下降吗?
  • 它的总和是否相同,但在加载和存储之间进行了划分?
  • 或者我可以使用整个规定的带宽进行存储整个规定的带宽进行存储吗?