以下是一些openmp 3.0代码:
#pragma omp parallel
{
#pragma omp single nowait
{
while(!texture_patches.empty())
{
int texture_size = calculate_texture_size(texture_patches, BORDER);
mve::ByteImage::Ptr texture = mve::ByteImage::create(texture_size, texture_size, 3);
mve::ByteImage::Ptr validity_mask = mve::ByteImage::create(texture_size, texture_size, 1);
//...
//the content of texture_patches changes here
//...
#pragma omp task
dilate_valid_pixel(texture, validity_mask);//has no effects on the content of texture_patches
}
#pragma omp taskwait
std::cout << "done. (Took: " << timer.get_elapsed_sec() << "s)" << std::endl;
}
}
众所周知,vs2010不支持openmp3.0。谁能告诉我如何调整上面的代码,以便它们可以在vs2010中使用?谢谢!
答案 0 :(得分:0)
我并不完全清楚dilate_valid_pixel(texture, validity_mask)
对texture_patches
的内容有何影响,但taskwait
位于{{1>} 之外的事件while
循环和缺少锁定指令/调用暗示dilate_valid_pixel()
任务决不会影响容器。在这种情况下,通常做的是预先填充工作项数组,然后使用并行循环处理数组。代码如下:
// Create work items in serial
std::vector<*WorkItem> work_items;
while(!texture_patches.empty()){
/* Try to insert each of the texture patches into the texture atlas. */
for (std::list<TexturePatch>::iterator it = texture_patches.begin(); it != texture_patches.end();){
TexturePatch texture_patch = *it;
// ...
if (bin.insert(&rect)){
it = texture_patches.erase(it);//Attention!!! texture_patches changes
remaining_patches--;
} else {
it++;
}
}
//#pragma omp task
//dilate_valid_pixel(texture, validity_mask);
work_items.push_back(new WorkItem(texture, validity_mask));
groups.push_back(group);
material_lib.add_material(group.material_name, texture);
}
// Process the work items in parallel
#pragma omp parallel for
for (int i = 0; i < work_items.size(); i++)
dilate_valid_pixel(work_items[i]->texture, work_items[i]->validity_mask);
std::cout << "done. (Took: " << timer.get_elapsed_sec() << "s)" << std::endl;
释放未显示的工作项的内存。原始任务代码保留在注释中。
一个重要方面:如果dilate_valid_pixel()
并不总是花费相同的时间来完成,那么将schedule(dynamic,1)
子句添加到parallel for
构造并使用块大小({ {1}})以获得最佳表现。
此代码与使用显式任务的代码并不完全等效,因为所有任务都是先创建然后执行,而原始代码与执行并行创建任务,即上面的代码执行起来会更糟(如果创建任务非常快(比如创建任务需要很长时间)比原始代码更糟糕。