在OpenMP循环中通过引用传递的vector更新是否安全?
在OpenMP并行函数内更新引用传递的vector是否安全?
这种操作是安全的,前提是每个线程操作的vector元素区间完全不重叠。
你的代码中,每个并行迭代的j对应out_vector中独立的一段区间[j*loop_vector_length, (j+1)*loop_vector_length),不同线程处理的区间没有任何交集——每个元素只会被一个线程写入,不存在同时读写或多线程写同一个元素的情况。这种封装在内部函数里的操作,和直接在并行循环内更新vector的安全性完全等价,函数调用只是把逻辑分层,不会改变内存访问的本质。
不过你的代码存在两个需要注意的问题:
std::srand和std::rand并非线程安全接口,多个线程同时调用srand会互相覆盖全局随机数种子,导致随机数生成结果混乱,甚至触发未定义行为。- 代码默认
vector_length是loop_vector_length的整数倍,如果实际长度不满足这个条件,最后一段未被整除的元素会被遗漏,需要处理边界场景。
以下是修复后的示例代码:
#include <omp.h> #include <vector> #include <cstddef> #include <random> void inner_fun(const std::vector<int>& in_vector, std::vector<int>& out_vector, const std::size_t j, const std::size_t loop_vector_length) { const std::size_t starting_index = j * loop_vector_length; // 使用线程局部的随机数生成器,避免线程间干扰 thread_local std::mt19937 rng(starting_index); thread_local std::uniform_int_distribution<int> dist(0, 9999); for(std::size_t i = starting_index; i < starting_index + loop_vector_length; ++i) { out_vector[i] = in_vector[i] + dist(rng); } } std::vector<int> outer_fun(const std::vector<int>& in_vector, const std::size_t loop_vector_length) { const std::size_t vector_length = in_vector.size(); std::vector<int> out_vector (vector_length); #pragma omp parallel for num_threads(5) for(std::size_t j = 0; j <= vector_length / loop_vector_length; ++j) { // 处理最后一段可能不足loop_vector_length的元素 const std::size_t actual_length = (j == vector_length / loop_vector_length) ? (vector_length - j * loop_vector_length) : loop_vector_length; if(actual_length == 0) continue; inner_fun(in_vector, out_vector, j, actual_length); } return out_vector; }
内容的提问来源于stack exchange,提问作者user
相关产品推荐
相关产品推荐

