Omp for循环初始化向量
Omp for loop initialize vector
我有以下代码:
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。我做错了什么?
您在这里看到的是线程不安全函数被多个线程调用的效果。在内部 push_back
在伪代码
中做了类似下面的事情
if reallocation needed:
reallocate
construct new object at &data[size]
++size
现在试着想象不同的线程运行同时执行上面的代码。如果两个线程都认为需要重新分配并同时尝试这样做,会发生什么情况。如果他们都在 &data[size]
构造一个对象,因为他们都在 ++size
之前到达那个点怎么办?请注意,即使尝试在与构造相同的行上递增也不起作用,因为它们仍然是独立的非原子操作。
您真正想要做的是创建一个严格线程安全操作的循环,如下所示。
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
调用,这会使它们比非并行方式慢。另一种解决方案是填充线程本地容器,然后合并它们。但是只要我上面显示的简单解决方案适用,它也会比替代方案更快。
我有以下代码:
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。我做错了什么?
您在这里看到的是线程不安全函数被多个线程调用的效果。在内部 push_back
在伪代码
if reallocation needed:
reallocate
construct new object at &data[size]
++size
现在试着想象不同的线程运行同时执行上面的代码。如果两个线程都认为需要重新分配并同时尝试这样做,会发生什么情况。如果他们都在 &data[size]
构造一个对象,因为他们都在 ++size
之前到达那个点怎么办?请注意,即使尝试在与构造相同的行上递增也不起作用,因为它们仍然是独立的非原子操作。
您真正想要做的是创建一个严格线程安全操作的循环,如下所示。
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
调用,这会使它们比非并行方式慢。另一种解决方案是填充线程本地容器,然后合并它们。但是只要我上面显示的简单解决方案适用,它也会比替代方案更快。