我正在尝试使用OpenMP并行化以下C函数:
struct pixel {
double r, g, b;
};
double min_dist_sum_parallel(struct pixel *pixels, int n_pixels,
struct pixel *centroids, int n_centroids)
{
double t0 = omp_get_wtime();
double min_dist_sum = 0.0;
#pragma omp parallel for reduction(+:min_dist_sum)
for (int i = 0; i < n_pixels; ++i) {
int closest_centroid = 0;
double min_dist = DBL_MAX;
for (int j = 0; j < n_centroids; ++j) {
double dr = pixels[i].r - centroids[j].r;
double dg = pixels[i].g - centroids[j].g;
double db = pixels[i].b - centroids[j].b;
double dist = sqrt(dr * dr + dg * dg + db * db);
if (dist < min_dist) {
closest_centroid = j;
min_dist = dist;
}
}
min_dist_sum += min_dist;
}
return min_dist_sum;
}
我已在具有两个CPU内核的机器上测试了这一点,每个内核支持两个超线程。通过设置OMP_NUM_THREAD环境变量将OpenMP线程的最大数量限制为2,可以将程序加速大约两倍(如预期的那样),以获得足够的问题大小(例如,n_pixels = 1000000,n_centroids = 10)。
另一方面,允许三个线程不会产生进一步的性能提升,事实上程序平均比双线程情况下运行速度慢约10%。四个线程的性能再次类似于两个线程的性能。
我相信我理解为什么会这样:因为在内存访问之间没有执行特别耗费计算的操作,同一CPU内核上的多个超线程无法有效地共享工作负载。
这个解释听起来不错?在任何情况下,我都不明白这将如何解释三个OpenMP线程比两个或四个慢。