首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用于循环初始化向量的Omp

用于循环初始化向量的Omp
EN

Stack Overflow用户
提问于 2019-03-09 20:45:38
回答 1查看 228关注 0票数 0

我有以下代码:

代码语言:javascript
复制
int main() {
vector<int> vec;

#pragma omp parallel for ordered schedule(dynamic)            
for (int i = 0; i <= 300; i++) {
    vec.push_back(i);
} 
cout << vec.size() << endl;
}

向量大小有时是285或294,但绝不是301。我哪里做错了?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-03-09 21:23:32

你在这里看到的是线程不安全函数被多个线程调用的效果。在内部,push_back使用伪代码执行类似于以下内容的操作

代码语言:javascript
复制
if reallocation needed:
    reallocate
construct new object at &data[size]
++size

现在试着想象一下不同的线程同时运行上面的代码。如果两个线程都认为需要重新分配并同时尝试重新分配,会发生什么情况?如果他们都在&data[size]构造一个对象,因为他们都在++size之前达到了那个点,那会怎么样?请注意,即使尝试在与构造相同的行上递增,也不会起作用,因为它们仍然是独立的非原子操作。

你真正想做的是创建一个严格的线程安全操作循环,如下所示。

代码语言:javascript
复制
int main() {
    std::vector<int> vec(301);

    #pragma omp parallel for
    for (int i = 0; i <= 300; i++) {
        vec[i]= i;
    }
    std::cout << vec.size() << std::endl;
}

在本例中,每个线程都使用唯一的i访问vec[i]。因此,对于相同的对象,不会同时发生任何操作。这是绝对安全的。

为了回答你的后续问题,没有办法并发地push_back到一个向量中。您必须同步您的push_back调用,这将使它们比非并行方式更慢。另一种解决方案是填充线程本地容器,然后合并它们。但只要我上面展示的简单解决方案适用,它也会比替代方案更快。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/55077490

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档