【发布时间】:2015-08-18 01:56:15
【问题描述】:
我正在测试一些算法在使用 OpenMP 时的性能加速,其中之一是无法缩放。我做错了吗?
电脑详情:
- 内存: 7.7 GiB
- 处理器: Intel® Core™ i7-4770 CPU @ 3.40GHz × 8
- 操作系统: Ubuntu 15.04 64 位
- gcc: gcc (Ubuntu 4.8.2-19ubuntu1) 4.8.2
代码:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <omp.h>
int main(int argc, char **argv) {
int test_size, i;
double *vector, mean, stddeviation, start_time, duration;
if (argc != 2) {
printf("Usage: %s <test_size>\n", argv[0]);
return 1;
}
srand((int) omp_get_wtime());
test_size = atoi(argv[1]);
printf("Test Size: %d\n", test_size);
vector = (double *) malloc(test_size * sizeof(double));
for (i = 0; i < test_size; i++) {
vector[i] = rand();
}
start_time = omp_get_wtime();
mean = 0;
stddeviation = 0;
#pragma omp parallel default(shared) private(i)
{
#pragma omp for reduction(+:mean)
for (i = 0; i < test_size; i++) {
mean += vector[i];
}
#pragma omp single
mean /= test_size;
#pragma omp for reduction(+:stddeviation)
for (i = 0; i < test_size; i++) {
stddeviation += (vector[i] - mean)*(vector[i] - mean);
}
}
stddeviation = sqrt(stddeviation / test_size);
duration = omp_get_wtime() - start_time;
printf("Std. Deviation = %lf\n", stddeviation);
printf("Duration: %fms\n", duration*1000);
return 0;
}
编译行
gcc -c -o main.o main.c -fopenmp -lm -O3
gcc -o dp main.o -fopenmp -lm -O3
结果
$ OMP_NUM_THREADS=1 ./dp 100000000
166.224199ms
$ OMP_NUM_THREADS=2 ./dp 100000000
157.924034ms
$ OMP_NUM_THREADS=4 ./dp 100000000
159.056189ms
【问题讨论】:
-
是的,我想到了这个,然后我用 Go 重写了这段代码,得到了 167ms、84ms 和 31ms……你不认为 C 代码至少应该等于 Go 时间吗?
-
基准测试是对大量数据进行单次传递,并且几乎不做任何工作。它可能完全受内存限制。
-
@Mysticial,我同意它受内存带宽限制,但这并不意味着它不应该从使用多个线程 stackoverflow.com/questions/25179738/… 中看到一些显着的好处。所以我有点惊讶 OP 基本上没有缩放。但我现在没有时间考虑这个。
-
我无法重现您的结果。在 Ubuntu 15.04(和你一样)上用 gcc 4.8(和你一样)编译你的代码,取决于 CPU,2 个线程的加速在 1.13 到 1.83 之间——这大约是你对内存受限的期望像你这样的程序(循环展开和用纯内存访问替换浮点操作等实验证实它实际上是受内存限制的)。你 1.05 的加速似乎太低了,特别是考虑到我在与你最相似的系统上获得了最高加速。
-
您是否确认您获得了请求的线程数?你在做
OMP_NUM_THREADS=1 ./dp 100000000吗?还是你这样做是分开的?如果第二种情况你需要export OMP_NUM_THREADS=1 ./dp 100000000.