Skip to content

Commit 704416a

Browse files
committed
[features] change SHOT estimation to a dynamic schedule
1 parent 4db3dc4 commit 704416a

4 files changed

Lines changed: 197 additions & 7 deletions

File tree

benchmarks/CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@ PCL_ADD_BENCHMARK(features_normal_3d FILES features/normal_3d.cpp
1818
ARGUMENTS "${PCL_SOURCE_DIR}/test/table_scene_mug_stereo_textured.pcd"
1919
"${PCL_SOURCE_DIR}/test/milk_cartoon_all_small_clorox.pcd")
2020

21+
PCL_ADD_BENCHMARK(features_shot FILES features/shot.cpp
22+
LINK_WITH pcl_io pcl_search pcl_features
23+
ARGUMENTS "${PCL_SOURCE_DIR}/test/milk.pcd")
24+
2125
PCL_ADD_BENCHMARK(filters_voxel_grid FILES filters/voxel_grid.cpp
2226
LINK_WITH pcl_io pcl_filters
2327
ARGUMENTS "${PCL_SOURCE_DIR}/test/table_scene_mug_stereo_textured.pcd"

benchmarks/features/shot.cpp

Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
#include <pcl/features/normal_3d_omp.h>
2+
#include <pcl/features/shot_omp.h>
3+
#include <pcl/io/pcd_io.h>
4+
#include <pcl/point_cloud.h>
5+
#include <pcl/point_types.h>
6+
7+
#include <benchmark/benchmark.h>
8+
9+
static void
10+
BM_SHOT352(benchmark::State& state, const std::string& file)
11+
{
12+
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
13+
pcl::PCDReader reader;
14+
reader.read(file, *cloud);
15+
16+
pcl::NormalEstimationOMP<pcl::PointXYZ, pcl::Normal> ne;
17+
ne.setInputCloud(cloud);
18+
ne.setKSearch(10);
19+
pcl::PointCloud<pcl::Normal>::Ptr normals(new pcl::PointCloud<pcl::Normal>);
20+
ne.compute(*normals);
21+
22+
pcl::SHOTEstimation<pcl::PointXYZ, pcl::Normal, pcl::SHOT352> shot;
23+
shot.setInputCloud(cloud);
24+
shot.setInputNormals(normals);
25+
shot.setRadiusSearch(0.04);
26+
27+
pcl::PointCloud<pcl::SHOT352>::Ptr output(new pcl::PointCloud<pcl::SHOT352>);
28+
for (auto _ : state) {
29+
shot.compute(*output);
30+
}
31+
}
32+
33+
static void
34+
BM_SHOT352_OMP(benchmark::State& state, const std::string& file)
35+
{
36+
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
37+
pcl::PCDReader reader;
38+
reader.read(file, *cloud);
39+
40+
pcl::NormalEstimationOMP<pcl::PointXYZ, pcl::Normal> ne;
41+
ne.setInputCloud(cloud);
42+
ne.setKSearch(10);
43+
pcl::PointCloud<pcl::Normal>::Ptr normals(new pcl::PointCloud<pcl::Normal>);
44+
ne.compute(*normals);
45+
46+
pcl::SHOTEstimationOMP<pcl::PointXYZ, pcl::Normal, pcl::SHOT352> shot(
47+
0, state.range(0) //
48+
);
49+
shot.setInputCloud(cloud);
50+
shot.setInputNormals(normals);
51+
shot.setRadiusSearch(0.04);
52+
53+
pcl::PointCloud<pcl::SHOT352>::Ptr output(new pcl::PointCloud<pcl::SHOT352>);
54+
for (auto _ : state) {
55+
shot.compute(*output);
56+
}
57+
}
58+
59+
static void
60+
BM_SHOT1344(benchmark::State& state, const std::string& file)
61+
{
62+
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_xyz(new pcl::PointCloud<pcl::PointXYZ>);
63+
pcl::PCDReader reader;
64+
reader.read(file, *cloud_xyz);
65+
66+
pcl::NormalEstimationOMP<pcl::PointXYZ, pcl::Normal> ne;
67+
ne.setInputCloud(cloud_xyz);
68+
ne.setKSearch(10);
69+
pcl::PointCloud<pcl::Normal>::Ptr normals(new pcl::PointCloud<pcl::Normal>);
70+
ne.compute(*normals);
71+
72+
pcl::PointCloud<pcl::PointXYZRGBA>::Ptr cloud_rgba(
73+
new pcl::PointCloud<pcl::PointXYZRGBA>);
74+
75+
for (int i = 0; i < static_cast<int>(cloud_xyz->size()); ++i) {
76+
pcl::PointXYZRGBA p;
77+
p.x = (*cloud_xyz)[i].x;
78+
p.y = (*cloud_xyz)[i].y;
79+
p.z = (*cloud_xyz)[i].z;
80+
81+
p.rgba = ((i % 255) << 16) + (((255 - i) % 255) << 8) + ((i * 37) % 255);
82+
cloud_rgba->push_back(p);
83+
}
84+
85+
pcl::SHOTColorEstimation<pcl::PointXYZRGBA, pcl::Normal, pcl::SHOT1344> shot(true,
86+
true);
87+
shot.setInputCloud(cloud_rgba);
88+
shot.setInputNormals(normals);
89+
shot.setRadiusSearch(0.04);
90+
91+
pcl::PointCloud<pcl::SHOT1344>::Ptr output(new pcl::PointCloud<pcl::SHOT1344>);
92+
for (auto _ : state) {
93+
shot.compute(*output);
94+
}
95+
}
96+
97+
static void
98+
BM_SHOT1344_OMP(benchmark::State& state, const std::string& file)
99+
{
100+
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_xyz(new pcl::PointCloud<pcl::PointXYZ>);
101+
pcl::PCDReader reader;
102+
reader.read(file, *cloud_xyz);
103+
104+
pcl::NormalEstimationOMP<pcl::PointXYZ, pcl::Normal> ne;
105+
ne.setInputCloud(cloud_xyz);
106+
ne.setKSearch(10);
107+
pcl::PointCloud<pcl::Normal>::Ptr normals(new pcl::PointCloud<pcl::Normal>);
108+
ne.compute(*normals);
109+
110+
pcl::PointCloud<pcl::PointXYZRGBA>::Ptr cloud_rgba(
111+
new pcl::PointCloud<pcl::PointXYZRGBA>);
112+
113+
for (int i = 0; i < static_cast<int>(cloud_xyz->size()); ++i) {
114+
pcl::PointXYZRGBA p;
115+
p.x = (*cloud_xyz)[i].x;
116+
p.y = (*cloud_xyz)[i].y;
117+
p.z = (*cloud_xyz)[i].z;
118+
119+
p.rgba = ((i % 255) << 16) + (((255 - i) % 255) << 8) + ((i * 37) % 255);
120+
cloud_rgba->push_back(p);
121+
}
122+
123+
pcl::SHOTColorEstimationOMP<pcl::PointXYZRGBA, pcl::Normal, pcl::SHOT1344> shot(
124+
true, true, 0, state.range(0));
125+
shot.setInputCloud(cloud_rgba);
126+
shot.setInputNormals(normals);
127+
shot.setRadiusSearch(0.04);
128+
129+
pcl::PointCloud<pcl::SHOT1344>::Ptr output(new pcl::PointCloud<pcl::SHOT1344>);
130+
for (auto _ : state) {
131+
shot.compute(*output);
132+
}
133+
}
134+
135+
int
136+
main(int argc, char** argv)
137+
{
138+
if (argc < 2) {
139+
std::cerr << "No test files given. Please provide a PCD file paths for SHOT352 "
140+
"and SHOT1344 benchmarks."
141+
<< std::endl;
142+
return (-1);
143+
}
144+
145+
constexpr int runs = 100;
146+
147+
benchmark::RegisterBenchmark("BM_SHOT352", &BM_SHOT352, argv[1])
148+
->Unit(benchmark::kMillisecond)
149+
->Iterations(runs);
150+
benchmark::RegisterBenchmark("BM_SHOT352_OMP", &BM_SHOT352_OMP, argv[1])
151+
->Arg(64)
152+
->Arg(128)
153+
->Arg(256)
154+
->Unit(benchmark::kMillisecond)
155+
->Iterations(runs);
156+
157+
benchmark::RegisterBenchmark("BM_SHOT1344", &BM_SHOT1344, argv[1])
158+
->Unit(benchmark::kMillisecond)
159+
->Iterations(runs);
160+
benchmark::RegisterBenchmark("BM_SHOT1344_OMP", &BM_SHOT1344_OMP, argv[1])
161+
->Arg(64)
162+
->Arg(128)
163+
->Arg(256)
164+
->Unit(benchmark::kMillisecond)
165+
->Iterations(runs);
166+
167+
benchmark::Initialize(&argc, argv);
168+
benchmark::RunSpecifiedBenchmarks();
169+
}

features/include/pcl/features/impl/shot_omp.hpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,8 @@ pcl::SHOTEstimationOMP<PointInT, PointNT, PointOutT, PointRFT>::computeFeature (
153153
#pragma omp parallel for \
154154
default(none) \
155155
shared(output) \
156-
num_threads(threads_)
156+
num_threads(threads_) \
157+
schedule(dynamic, chunk_size_)
157158
for (std::ptrdiff_t idx = 0; idx < static_cast<std::ptrdiff_t> (indices_->size ()); ++idx)
158159
{
159160

@@ -240,7 +241,8 @@ pcl::SHOTColorEstimationOMP<PointInT, PointNT, PointOutT, PointRFT>::computeFeat
240241
#pragma omp parallel for \
241242
default(none) \
242243
shared(output) \
243-
num_threads(threads_)
244+
num_threads(threads_) \
245+
schedule(dynamic, chunk_size_)
244246
for (std::ptrdiff_t idx = 0; idx < static_cast<std::ptrdiff_t> (indices_->size ()); ++idx)
245247
{
246248
Eigen::VectorXf shot;

features/include/pcl/features/shot_omp.h

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -94,8 +94,12 @@ namespace pcl
9494
using PointCloudOut = typename Feature<PointInT, PointOutT>::PointCloudOut;
9595
using PointCloudIn = typename Feature<PointInT, PointOutT>::PointCloudIn;
9696

97-
/** \brief Empty constructor. */
98-
SHOTEstimationOMP (unsigned int nr_threads = 0) : SHOTEstimation<PointInT, PointNT, PointOutT, PointRFT> ()
97+
/** \brief Empty constructor.
98+
* \param nr_threads the number of hardware threads to use (0 sets the value back to automatic)
99+
* \param chunk_size PCL will use dynamic scheduling with this chunk size. Setting it too low will lead to more parallelization overhead. Setting it too high will lead to a worse balancing between the threads.
100+
*/
101+
explicit SHOTEstimationOMP (unsigned int nr_threads = 0, int chunk_size = 256)
102+
: SHOTEstimation<PointInT, PointNT, PointOutT, PointRFT> (), chunk_size_(chunk_size)
99103
{
100104
setNumberOfThreads(nr_threads);
101105
};
@@ -122,6 +126,9 @@ namespace pcl
122126

123127
/** \brief The number of threads the scheduler should use. */
124128
unsigned int threads_;
129+
130+
/** \brief Chunk size for (dynamic) scheduling. */
131+
int chunk_size_;
125132
};
126133

127134
/** \brief SHOTColorEstimationOMP estimates the Signature of Histograms of OrienTations (SHOT) descriptor for a given point cloud dataset
@@ -176,11 +183,16 @@ namespace pcl
176183
using PointCloudOut = typename Feature<PointInT, PointOutT>::PointCloudOut;
177184
using PointCloudIn = typename Feature<PointInT, PointOutT>::PointCloudIn;
178185

179-
/** \brief Empty constructor. */
186+
/** \brief Empty constructor.
187+
* \param nr_threads the number of hardware threads to use (0 sets the value back to automatic)
188+
* \param chunk_size PCL will use dynamic scheduling with this chunk size. Setting it too low will lead to more parallelization overhead. Setting it too high will lead to a worse balancing between the threads.
189+
*/
180190
SHOTColorEstimationOMP (bool describe_shape = true,
181191
bool describe_color = true,
182-
unsigned int nr_threads = 0)
183-
: SHOTColorEstimation<PointInT, PointNT, PointOutT, PointRFT> (describe_shape, describe_color)
192+
unsigned int nr_threads = 0,
193+
int chunk_size = 64)
194+
: SHOTColorEstimation<PointInT, PointNT, PointOutT, PointRFT> (describe_shape, describe_color),
195+
chunk_size_(chunk_size)
184196
{
185197
setNumberOfThreads(nr_threads);
186198
}
@@ -207,6 +219,9 @@ namespace pcl
207219

208220
/** \brief The number of threads the scheduler should use. */
209221
unsigned int threads_;
222+
223+
/** \brief Chunk size for (dynamic) scheduling. */
224+
int chunk_size_;
210225
};
211226

212227
}

0 commit comments

Comments
 (0)