下面的并行循环导致以后出现几个错误:
#pragma omp parallel for schedule(dynamic, omp_get_num_procs())
for (int i = 0; i < (int)my_vector.size(); i++) {
cur = new My_Class(args);
cur->do_work();
my_instances_vector.push_back(cur);
}
有时程序只是段错误,有时它会提供memory corruption
或其他与访问相关的错误,有时会导致意外行为。按顺序执行实例化并且并行工作可以解决问题:
for (int i = 0; i < (int)my_vector.size(); i++) {
cur = new My_Class(args);
my_instances_vector.push_back(cur);
}
#pragma omp parallel for schedule(dynamic, omp_get_num_procs())
for (i = 0; i < (int)my_instances_vector.size(); i++) {
my_instances_vector[i]->do_work();
}
然而,有没有办法让它们并行?我认为这是一个简单的范围问题与实例指针,因为每个线程都有自己的范围,然后我需要访问并行区域外的每个实例的地址。主程序的其余部分基本上是
for (i = 0; i < (int)my_instances_vector.size(); i++) {
my_instances_vector[i]->print_results(); // Should be done sequentially
}
my_instances_vector.clear();
return(EXIT_SUCCESS);
我为lasprivate
和shared
尝试了cur
和/或my_instances_vector
的所有可能组合。它导致了相同的错误或竞争条件。我找到的唯一“解决方案”是无实例化实例化。我正在做什么有什么问题,或者这是我班级内容的特定错误?类构造函数基本上根据传递的参数定义某些字段的值。其中涉及一些动态分配。也许这些地址“丢失了”?
答案 0 :(得分:2)
问题(正如@zboson正确指出的那样)是push_back
期间的数据争用。不过,我想提出一个不同的解决方案,这可能更容易实现:
size_t offset = my_instances_vector.size;
// Pre-allocate space for the right number of pointers
// and set them to nullptr
my_instances_vector.insert(my_instances_vector.end(),my_vector.size(),nullptr);
#pragma omp parallel for schedule(dynamic, chunksize)
for (size_t ii = 0; ii < my_vector.size(); ii++) {
my_instances_vector[offset + ii] = new My_Class(args); // Create the object
my_instances_vector[offset + ii]->do_work(); // work on it
}
正如您所看到的,代码是无数据争用的,因为每个线程都在其my_instances_vector
元素上工作。
未请求建议:请关注内存管理!在向量中使用原始指针可能会在程序中留下泄漏,并且会导致代码难以维护,因为向量不负责删除使用new
分配的资源。我建议看看RAII习语和C ++ 11 std::shared_ptr
及相关方法(例如make_shared
替换new
)。
答案 1 :(得分:1)
问题是std :: vector不是线程安全的。每个线程都可以增加向量的大小并更改其内存位置。修复此问题的方法是让每个线程写入其自己的私有版本的向量,然后将它们合并到一个关键部分。在你的情况下,你可以这样做
#pragma omp parallel
{
vector<My_class*> my_instances_vector_private;
#pragma omp for schedule(dynamic, omp_get_num_procs()) nowait
for (int i = 0; i < (int)my_vector.size(); i++) {
My_class *cur = new My_Class(args);
cur->do_work();
my_instances_vector_private.push_back(cur);
}
#pragma omp critical
my_instances_vector.insert(my_instances_vector.end(), my_instances_vector_private.begin(), my_instances_vector_private.end());
}
这假定args
是一个常数,或者它只是i
的函数而不是i-1
的函数。 {{1}}。