为什么OpenMP没有并行化vtk IntersectWithLine代码

时间:2017-08-09 11:36:59

标签: c++ multithreading parallel-processing openmp vtk

我无法理解为什么如果在循环内部执行Vtk代码,与OpenMP并行化的 for循环不会使用所有FirefoxProfile profile = new FirefoxProfile(); //Set Location to store files after downloading. profile.setPreference("browser.download.folderList", 2); profile.setPreference( "browser.download.manager.showWhenStarting", false ); profile.setPreference("browser.download.dir", "D:\\WebDriverDownloads"); profile.setPreference("pdfjs.disabled", true); profile.setPreference("browser.helperApps.neverAsk.saveToDisk", "application/pdf"); System.setProperty("webdriver.firefox.bin", "D:\\FFF\\firefox.exe"); driver = new FirefoxDriver(profile); 个线程(= 2x #cores)。具体来说,我想用线条相交线条/光线。我跟着this tutorial 跟着

  1. 从网格构建OBB树
  2. 将所有必需的线与网格相交
  3. 因为我想并行化它,所以我创建了n_threads树,这样每个线程都可以使用它自己的树实例:

    n_threads

    然后我遍历所有点以计算// Pre-allocate the array int n_threads = omp_get_max_threads(); trees = std::vector<vtkSmartPointer<vtkOBBTree>>((unsigned int) n_threads); // Build n_threads OBB trees #pragma omp parallel for num_threads(n_threads) for (int t = 0; t < n_threads; ++t) { trees[t] = vtkSmartPointer<vtkOBBTree>::New(); vtkSmartPointer<vtkPolyData> mesh_clone = vtkSmartPointer<vtkPolyData>::New(); #pragma omp critical (build_mesh_tree) { mesh_clone->DeepCopy(mesh); } trees[t]->SetDataSet(mesh_clone); trees[t]->BuildLocator(); } origin

    中每个点之间的交点
    points

    OpenMP已经证明可以按照预期的方式使用简单的C ++代码。但是当围绕Vtk调用时,它无法实现其目的。我想这是因为Vtk已经提供parallelization frameworkref. to the guide)。

    如果是这种情况,您能解释一下,为什么OpenMP无法并行运行与vtk相关的代码?如果没有,可能是什么原因?

1 个答案:

答案 0 :(得分:0)

它到底是怎么失败的?你有没有尝试过例如打印线程号以查看是否生成了n_threads?如果你在intersection_pointscell_ids“只是”得到错误的结果,那是因为每当他们进入IntersectWithLine函数时,每个线程都会重置这些数组(你可以看看实现here,第800-808行。

要解决这个问题,最容易想到的解决方案是让每个线程拥有自己的列表,然后在一个关键部分连接它们,但更快的可能是为每个线程预先分配这些列表的数组然后再读取结果,例如:

vtkSmartPointer<vtkPoints> *inter_points = new vtkSmartPointer<vtkPoints> [n_threads];
vtkSmartPointer<vtkIdList> *inter_cells = new vtkSmartPointer<vtkIdList> [n_threads];
for (unsigned long i = 0; i < n_threads; ++i)
{
    inter_points[i] = vtkSmartPointer<vtkPoints>::New();
    inter_cells[i] = vtkSmartPointer<vtkIdList>::New();
}

#pragma omp parallel for num_threads(n_threads)
for (unsigned long i = 0; i < n_points; ++i)
{
    int this_thread = omp_get_thread_num();
    int code = trees[this_thread]->IntersectWithLine(
            origin.data(), // pointer to the raw data
            points.at(i).data(), // buffer of a Eigen matrix
            inter_points[this_thread],
            inter_cells[this_thread);
}

// now concatenate the results to one array if necessarry

(没有编译,可能有语法错误,只是普通的C,所以不是最安全的方式......)