向量的矩阵乘法OpenMP C
我试图通过C(OpenMP)中的向量乘法来编写Matrix,但是当我添加处理器时我的程序会变慢…
1 proc - 1,3 s 2 proc - 2,6 s 4 proc - 5,47 s
我在我的PC(核心i5)和我们学校的集群上进行了测试,结果相同(程序运行缓慢)
这是我的代码(矩阵是10000 x 10000),矢量是10000:
double start_time = clock(); #pragma omp parallel private(i) num_threads(4) { tid = omp_get_thread_num(); world_size = omp_get_num_threads(); printf("Threads: %d\n",world_size); for(y = 0; y < matrix_size ; y++){ #pragma omp parallel for private(i) shared(results, vector, matrix) for(i = 0; i < matrix_size; i++){ results[y] = results[y] + vector[i]*matrix[i][y]; } } } double end_time = clock(); double result_time = (end_time - start_time) / CLOCKS_PER_SEC; printf("Time: %f\n", result_time);
我的问题是:有什么错误吗? 对我来说,它看起来很简单,应该加快速度
我本质上已经回答了这个问题并行化 – 矩阵 – 时间 – 矢量逐列和逐行 – 与openmp 。
当您写入results[y]
时,您会遇到竞争条件。 要解决此问题,并仍然并行化内部循环,您必须创建results[y]
私有版本results[y]
,并行填充它们,然后将它们合并到一个关键部分。
在下面的代码中,我假设您正在使用double
,将其替换为float
或int
或您正在使用的任何数据类型(请注意,您的内部循环遍历matrix[i][y]
的第一个索引,这是缓存不友好的)。
#pragma omp parallel num_threads(4) { int y,i; double* results_private = (double*)calloc(matrix_size, sizeof(double)); for(y = 0; y < matrix_size ; y++) { #pragma omp for for(i = 0; i < matrix_size; i++) { results_private[y] += vector[i]*matrix[i][y]; } } #pragma omp critical { for(y=0; y
如果这是家庭作业,你想真正给你的教练留下深刻印象,那么就可以在没有关键部分的情况下进行合并。 看到这个链接,了解如何做填充直方图 - arrays减少 - 并行 - 使用openmp-without-using-a-critic虽然我不能保证它会更快。
我暂时没有进行任何并行编程,也没有任何数学,但是你不想并行分割矩阵的行而不是列吗?
如果您尝试这样做会发生什么:
double start_time = clock(); #pragma omp parallel private(i) num_threads(4) { tid = omp_get_thread_num(); world_size = omp_get_num_threads(); printf("Threads: %d\n",world_size); #pragma omp parallel for private(y) shared(results, vector, matrix) for(y = 0; y < matrix_size ; y++){ for(i = 0; i < matrix_size; i++){ results[y] = results[y] + vector[i]*matrix[i][y]; } } } double end_time = clock(); double result_time = (end_time - start_time) / CLOCKS_PER_SEC; printf("Time: %f\n", result_time);
此外,你确定一切正常编译和与openMP
链接?
您有一个典型的缓存冲突案例。
考虑到CPU上的缓存行可能长达64个字节。 让一个处理器/核心写入前4个字节( float
)会导致该高速缓存行在每个其他L1 / L2和L3上无效。 这是很多开销。
更好地划分数据!
#pragma omp parallel for private(i) shared(results, vector, matrix) schedule(static,16)
应该做的伎俩。 如果这没有帮助,请增加chunksize。
另一个优化是在将结果刷新到内存之前将结果存储在本地。
此外,这是一个OpenMP的东西,但你不需要为循环启动一个新的并行区域(每次提及parallel
启动一个新的团队):
#pragma omp parallel default(none) \ shared(vector, matrix) \ firstprivate(matrix_size) \ num_threads(4) { int i, y; #pragma omp for schedule(static,16) for(y = 0; y < matrix_size ; y++){ double result = 0; for(i = 0; i < matrix_size; i++){ results += vector[i]*matrix[i][y]; } result[y] = result; } }