C语言并行编程:N=8线程作业仅运行至N=6的问题求助
问题分析与解决方向
核心问题1:任务划分逻辑被多余的索引检查破坏
你的代码中checkIndex和addIndex完全是多余的——因为你已经通过i*2和步长N明确划分了每个线程(或串行循环中的每个i)要处理的索引范围,这些范围完全不重叠,根本不需要检查索引是否被处理过。
比如:
- i=0处理的索引是0,1,9,10,18,19...
- i=1处理的是2,3,11,12,20,21...
- ...
- i=7处理的是14,15,23,24,32,33...
但串行运行时,前面的i会把后面i要处理的索引提前加入arrIndex,导致后面的i进入循环后,checkIndex返回true,跳过处理,所以你看不到i=6、7的输出。
核心问题2:并行化的线程安全与实现问题
你注释掉了OpenMP的并行指令,实际开启并行后,全局变量index会引发数据竞争,多个线程同时修改index会导致内存错误或逻辑混乱,但同样,这个变量完全不需要存在。
修复步骤
1. 删除多余的索引检查逻辑
直接去掉checkIndex、addIndex函数,以及全局变量index、数组arrIndex——任务划分是静态且无重叠的,不需要这些来保证唯一性。
2. 修正并行化实现
用OpenMP的线程号来分配任务,而不是串行循环模拟。修改后的核心代码如下:
#include <stdio.h> #include <stdlib.h> #include <omp.h> #define N 8 #define M 1000 int main() { int a[M]; int b[M]; int c[M]; // 初始化数组 for (int i = 0; i < M; i++) { a[i] = rand(); b[i] = rand(); c[i] = 0; } // 开启8线程并行区域 #pragma omp parallel num_threads(N) { int tid = omp_get_thread_num(); printf("%d: ", tid); // 每个线程处理对应的索引范围 for (int y = tid * 2; y < M; y += N) { c[y] = a[y] + b[y]; printf("%d ", y); y++; if (y < M) { // 防止y超出数组边界 c[y] = a[y] + b[y]; printf("%d ", y); } } printf("\n"); } return 0; }
3. 编译与运行
使用支持OpenMP的编译器编译,比如GCC:
gcc -fopenmp your_code.c -o parallel_add ./parallel_add
关键说明
- 任务划分逻辑:每个线程
tid从tid*2开始,每次步长为N(8),每次循环处理两个连续索引,完全符合你的期望输出。 - 线程安全:删除了所有共享的全局变量,每个线程只处理自己的索引范围,没有数据竞争。
- 边界处理:添加了
if (y < M)判断,避免当y++后超出数组边界(比如M为奇数时)。
内容的提问来源于stack exchange,提问作者Aeri
相关产品推荐
相关产品推荐

