2016-04-25 17 views
0

3D Point Cloudの法線ベクトルを推定する関数を作成しました。サイズが200万の雲の上を走るには多くの時間がかかります。私は、同時に2つの異なるポイントで同じ関数を呼び出すことによってマルチスレッドにしたいが、それは動作しなかった(それは何百ものスレッドを作成していた)。ここで私が試したものです:C++でポイントクラウドを反復処理するループ内でマルチスレッドを使用する方法は?

// kd-tree used for finding neighbours 
pcl::KdTreeFLANN<pcl::PointXYZRGB> kdt; 

// cloud iterators 
pcl::PointCloud<pcl::PointXYZRGB>::iterator cloud_it = pt_cl->points.begin(); 
pcl::PointCloud<pcl::PointXYZRGB>::iterator cloud_it1; 
pcl::PointCloud<pcl::PointXYZRGB>::iterator cloud_it2; 
pcl::PointCloud<pcl::PointXYZRGB>::iterator cloud_it3; 
pcl::PointCloud<pcl::PointXYZRGB>::iterator cloud_it4; 

// initializing tree 
kdt.setInputCloud(pt_cl); 

// loop exit condition 
bool it_completed = false; 

while (!it_completed) 
{ 
    // initializing cloud iterators 
    cloud_it1 = cloud_it; 
    cloud_it2 = cloud_it++; 
    cloud_it3 = cloud_it++; 

    if (cloud_it3 != pt_cl->points.end()) 
    { 
     // attaching threads 
     boost::thread thread_1 = boost::thread(geom::vectors::find_normal, pt_cl, cloud_it1, kdt, radius, max_neighbs); 
     boost::thread thread_2 = boost::thread(geom::vectors::find_normal, pt_cl, cloud_it2, kdt, radius, max_neighbs); 
     boost::thread thread_3 = boost::thread(geom::vectors::find_normal, pt_cl, cloud_it3, kdt, radius, max_neighbs); 

     // joining threads 
     thread_1.join(); 
     thread_2.join(); 
     thread_3.join(); 

     cloud_it++; 
    } 

    else 
    { 
     it_completed = true; 
    } 
} 

私は同じ機能を3つの異なるポイントで同時に呼び出そうとしています。どのようにこの作品を作るための任意の提案?申し訳ありませんが、コードが貧弱なため、私は疲れており、事前に感謝します。

編集:ここにここにパラメータがあるfind_normal機能 です:私は非常に結果のデータが格納されているどのようにそれを得ることはありませんので、私は上のベースのソリューションを提案するつもりです

@param pt_cl is a pointer to the point cloud to be treated (pcl::PointCloud<PointXYZRGB>::Ptr) 
@param cloud_it is an iterator of this cloud (pcl::PointCloud<PointXYZRGB>::iterator) 
@param kdt is the kd_tree used to find the closest neighbours of a point 
@param radius defines the range in which to search for the neighbours of a point 
@param max_neighbs is the maximum number of neighbours to be returned by the radius search 

// auxilliary vectors for the k-tree nearest search 
    std::vector<int> pointIdxRadiusSearch; // neighbours ids 
    std::vector<float> pointRadiusSquaredDistance; // distances from the source to the neighbours 

    // the vectors of which the cross product calculates the normal 
    geom::vectors::vector3 *vect1; 
    geom::vectors::vector3 *vect2; 
    geom::vectors::vector3 *cross_prod; 
    geom::vectors::vector3 *abs_cross_prod; 
    geom::vectors::vector3 *normal; 
    geom::vectors::vector3 *normalized_normal; 

    // vectors to average 
    std::vector<geom::vectors::vector3> vct_toavg; 

    // if there are neighbours left 
    if (kdt.radiusSearch(*cloud_it, radius, pointIdxRadiusSearch, pointRadiusSquaredDistance, max_neighbs) > 0) 
    { 

     for (int pt_index = 0; pt_index < (pointIdxRadiusSearch.size() - 1); pt_index++) 
     { 
      // defining the first vector 
      vect1 = geom::vectors::create_vect2p((*cloud_it), pt_cl->points[pointIdxRadiusSearch[pt_index + 1]]); 

      // defining the second vector; making sure there is no 'out of bounds' error 
      if (pt_index == pointIdxRadiusSearch.size() - 2) 
       vect2 = geom::vectors::create_vect2p((*cloud_it), pt_cl->points[pointIdxRadiusSearch[1]]); 


      else 
       vect2 = geom::vectors::create_vect2p((*cloud_it), pt_cl->points[pointIdxRadiusSearch[pt_index + 2]]); 

      // adding the cross product of the two previous vectors to our list 
      cross_prod = geom::vectors::cross_product(*vect1, *vect2); 
      abs_cross_prod = geom::aux::abs_vector(*cross_prod); 
      vct_toavg.push_back(*abs_cross_prod); 

      // freeing memory 
      delete vect1; 
      delete vect2; 
      delete cross_prod; 
      delete abs_cross_prod; 
     } 

     // calculating the normal 
     normal = geom::vectors::vect_avg(vct_toavg); 

     // calculating the normalized normal 
     normalized_normal = geom::vectors::normalize_normal(*normal); 

     // coloring the point 
     geom::aux::norm_toPtRGB(&(*cloud_it), *normalized_normal); 

     // freeing memory 
     delete normal; 
     delete normalized_normal; 

     // clearing vectors 
     vct_toavg.clear(); 
     pointIdxRadiusSearch.clear(); 
     pointRadiusSquaredDistance.clear(); 

     // shrinking vectors 
     vct_toavg.shrink_to_fit(); 
     pointIdxRadiusSearch.shrink_to_fit(); 
     pointRadiusSquaredDistance.shrink_to_fit(); 
    } 
+0

Boostで行ったようなスレッドを明示的に使用することは、このタスクでは残念です。 OpenMPと同様のライブラリ(Cilk、TBB)を見てください。 – iksemyonov

+0

また、望ましい結果をよりよく定義する必要があるようです。現時点では、すべての点を独立して並列に処理したいのか、関数を点に適用するときにあるパターンがあるのか​​(「2点で同じ関数を呼び出す」)は明確ではありません。 – iksemyonov

+0

それは間違いなく動作しません。私はTBBについて聞いたことがありますが、私のポイントクラウドで動作するかどうかはわかりません。私はそれを試してみる、ありがとう。 –

答えて

0

あなたが投稿したコードと一致するOpenMP。

// kd-tree used for finding neighbours 
pcl::KdTreeFLANN<pcl::PointXYZRGB> kdt; 

#pragma openmp parallel for schedule(static) 
for (pcl::PointCloud<pcl::PointXYZRGB>::iterator cloud_it = pt_cl->points.begin(); 
    cloud_it < pt_cl.end(); 
    ++cloud_it) { 
    geom::vectors::find_normal, pt_cl, cloud_it, kdt, radius, max_neighbs); 
} 

あなたが<比較を使用する必要があります注意、およびない!= 1、 - つまりは、OpenMPがどのように動作するかだ(それはランダムアクセスイテレータを望んでいます)。私はstaticスケジュールを使用しています。これは、すべての要素が処理する時間が多少なりとも同じでなければならないからです。そうでない場合は、schedule(dynamic)を代わりに使用してみてください。

このソリューションではOpenMPを使用しています。 TBBも同様ですが、OpenMPよりも進入障壁が高く、OOPスタイルのAPIを使用しています。

また、私がすでにコメントしたことを繰り返して、OpenMPとTBBはスレッド管理と負荷分散を処理します。あなたのニーズに合った方法でヒント(例:schedule(static))を渡すだけです。

他にもできるだけ小さなコードを繰り返す習慣をつけてください。理想的には、コードを複製する必要はありません。例えば。同じ型の多くの変数を宣言したり、類似のパターンを持つ行の中で特定の関数を何回か呼び出すと、そのコードの後ろにはっきりとした理由があるので、コードに過剰なコメントが表示されます。

+0

それは本当に良いように見える、それは間違いなく開始する場所です。結果データは、最後にテキストファイルにのみ保存されます。クラウド内のポイントには直接変換が行われます。つまり、保存するために作成された新しいクラウドはありません。プロセスは以下の通りです: >私はテキストファイルから雲を読みました。 >私はいくつかの操作を実行します。 >変換されたクラウド(同じ参照ですが、変更されたクラウド)をファイルに書き出します。 –

+0

@VladAdrianMoglan、今私は一般的な考えを得る。結果が同じ位置*に戻った場合、私のコードは動作するようになります。しかし、要素 'i'を取り出し、結果を別の位置' j'に置く場合を見てください! – iksemyonov

+0

そうです、そうです。とにかく、助けを求めるспасибо –

関連する問題