a3m*_*ord 8 performance ram multithreading bandwidth openmp
测量我的应用程序(使用OpenMP编写的多线程)使用的带宽的最简单,最有效的方法是什么?我跑了STREAM以获得最大值.可持续的带宽,我现在想知道我是否正在使整个可用带宽饱和.
我找到了几个相关的问题(例如主内存带宽测量),但我找不到这个问题的答案;
可悲的是,我不能使用VTune,但我可以使用PAPI计数器;
我的主要目标是找出我的应用程序的可扩展性是否与内存带宽的饱和度相关联.
谢谢
要测量应用程序的带宽,您需要知道正在读取和/或写入多少内存,我们将其称为分子,并且您需要知道读取和/或写入它需要多少时间,我们将其称为分子分母。带宽是分子/分母。
如果您的应用程序很复杂,那么计算正在读取和/或写入的内存量可能并不那么容易。此外,如果您的应用程序正在执行许多其他操作,则计算时间可能并不容易。您必须减去其他操作的时间。因此,在测量最大吞吐量时,通常使用简单的算法。
如果您想选择一种类似算法来尝试与您的应用程序进行比较,那么您应该看看您的应用程序是否只写入数据、只读取数据,还是同时读取和写入。
如果您只写入数据,则可以使用写入(memset)测试:
#pragam omp parallel for
for(int i=0; i<n; i++) {
x[i] = k;
}
Run Code Online (Sandbox Code Playgroud)
如果您同时读取和写入数据,则可以进行简单的复制(memcpy)测试
#pragma omp parallel for
for(int i=0; i<n; i++) {
y[i] = x[i];
}
Run Code Online (Sandbox Code Playgroud)
事实上,如果您查看 STREAM 源代码,您就会发现它基本上就是用于复制测试的。
-ffast-math
如果您只读取数据,您可以像这样进行减少(如果您希望对其进行矢量化,请确保进行编译):
#pragma omp parallel for reduction(+:sum)
for(int i=0; i<n; i++) {
sum += x[i]*y[i];
}
Run Code Online (Sandbox Code Playgroud)
STREAM的测试都是读写测试。我编写了自己的带宽工具,它只写、读和写以及只读。
不幸的是,写入数据的测试不会接近峰值带宽。原因是为了写入数据,他们必须首先将数据读入缓存。这就是 STREAM 无法接近我系统上的峰值带宽的原因。为了在写入时获得峰值带宽,您需要进行非临时存储,即仅写入数据而不首先将其读入缓存。
例如,使用 SSE 并假设x
和y
是浮点数组,您可以像这样进行读写测试:
#pragma omp parallel for
for(int i=0; i<n/4; i++) {
__m128 v = _mm_load_ps(&x[4*i]);
_mm_stream_ps(&y[4*i], v);
}
Run Code Online (Sandbox Code Playgroud)
如果您查看 Agner Fog 的asmlib,您会发现这正是他为大型数组所做的memset
事情memcpy
。事实上,他的 asmlib 和我刚刚给出的示例在我的系统上获得了 85%(51 GB/s 中的 45 GB/s)的带宽,而STREAM 测试仅获得了大约 45% 的带宽。
这些测试假设您的算法受内存限制,并且为了进行比较,您读取的数组比最慢的缓存大得多。如果您的算法重用仍在缓存中的数据,则由于循环依赖性,读取测试也不会接近峰值带宽。要解决此问题,您必须展开 3-10 次,具体取决于操作和硬件。另外,如果您正在对适合您将重用的缓存的数组进行写入,那么您不想进行非临时存储。这就是为什么 Agner Fog 的 asmlib 仅对大型数组使用非临时存储。
归档时间: |
|
查看次数: |
935 次 |
最近记录: |