【问题标题】:This predefined function slowing down my program's performance这个预定义的函数会降低我的程序性能
【发布时间】:2016-06-10 16:47:16
【问题描述】:

我正在从事 PCL(点云库)项目。其中一部分需要我裁剪点云,为此我需要知道给定点云的最小和最大坐标。

PCL 提供了一个名为 getminmax3d() 的预定义函数。我试过了,效果很好,唯一的问题是,输入大点云文件需要很长时间。我对 getminmax3d() 做了自己的定义,它需要更少的时间。我不明白为什么这两个行为会这样。

我尝试了 5 个点云数据文件。在所有情况下,与我定义的程序相比,使用预定义函数的程序都需要很长时间。

代码如下:
第一个实现 - 它使用预定义的函数 getminmax3d()

#include <iostream>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/common/common.h>

int main (int, char**)
{
  pcl::PointCloud<pcl::PointXYZ>::Ptr cloud;
  cloud = pcl::PointCloud<pcl::PointXYZ>::Ptr (new pcl::PointCloud<pcl::PointXYZ>);
  pcl::io::loadPCDFile<pcl::PointXYZ> ("your_pcd_file.pcd", *cloud);
  pcl::PointXYZ minPt, maxPt;
  pcl::getMinMax3D (*cloud, minPt, maxPt);
  std::cout << "Max x: " << maxPt.x << std::endl;
  std::cout << "Max y: " << maxPt.y << std::endl;
  std::cout << "Max z: " << maxPt.z << std::endl;
  std::cout << "Min x: " << minPt.x << std::endl;
  std::cout << "Min y: " << minPt.y << std::endl;
  std::cout << "Min z: " << minPt.z << std::endl;
  return (0);
}

第二个实现 - 此源代码使用用户定义的函数定义来替换 getminmax3d()

的功能
#include <iostream>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/common/time.h>

int main (int argc, char** argv)
{
   pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>);
   if (pcl::io::loadPCDFile<pcl::PointXYZ> ("rhino.pcd", *cloud) == -1) //* load the file
   {
     PCL_ERROR ("Couldn't read file rhino.pcd \n");
     return (-1);
   }
   float min_x = cloud->points[0].x, min_y = cloud->points[0].y, min_z = cloud->points[0].z, max_x = cloud->points[0].x, max_y = cloud->points[0].y, max_z = cloud->points[0].z;
   pcl::StopWatch watch;
   for (size_t i = 1; i < cloud->points.size (); ++i){
       if(cloud->points[i].x <= min_x )
           min_x = cloud->points[i].x;
       else if(cloud->points[i].y <= min_y )
           min_y = cloud->points[i].y;
       else if(cloud->points[i].z <= min_z )
           min_z = cloud->points[i].z;
       else if(cloud->points[i].x >= max_x )
           max_x = cloud->points[i].x;
       else if(cloud->points[i].y >= max_y )
           max_y = cloud->points[i].y;
       else if(cloud->points[i].z >= max_z )
           max_z = cloud->points[i].z;
   }
   pcl::console::print_highlight ("Time taken: %f\n", watch.getTimeSeconds());
   std::cout << "Min x: " << min_x <<"\t";
   std::cout << "Max x: " << max_x << std::endl;
   std::cout << "Min y: " << min_y <<"\t";
   std::cout << "Max y: " << max_y << std::endl;
   std::cout << "Min z: " << min_z <<"\t";
   std::cout << "Max z: " << max_z << std::endl;
   return (0);
}

我在以下 5 个点云文件上尝试了这两个程序。

获得的结果:
ttf:耗时系数
ttf = 15 表示用户定义比预定义函数快约 15 倍。 ttf 值是通过对两种实现进行平均 10 次试验来衡量的。

PCD file    Filetype   File size    ttf
Rhino.pcd   XYZ        2.57 MB      15.260
Bun_zipper  XYZCI      1.75 MB      17.422
Armadillo   XYZ        5.26 MB      15.847
Dragon_vrip XYZ        14.7 MB      17.013
Happy_vrip  XYZ        18.0 MB      14.981

我想知道为什么预定义函数需要更多时间?我想减少我的程序源代码行。我一直认为使用标准头文件及其功能可以为您提供最佳性能,但在这种情况下似乎失败了。

This is where you can find standard definition. 谁能帮我找出为什么第二次实现需要更少的时间(大约 15 次),即使 getminmax3d() 的标准定义与我的相似。

【问题讨论】:

  • 您的意思是 docs.pointclouds.org/1.7.2/… 作为文档链接吗?您的示例代码调用了该函数的 3 参数版本,但您链接到具有多个参数的版本
  • 有据可查的问题,赞成。关于“我一直相信使用标准头文件及其功能可以为您提供最佳性能”:并非总是如此。通常,标准函数必须处理对您的特定情况无用的极端情况,或者过于笼统,或者使用较旧的编译器版本编译,具有较不积极的优化设置或针对较旧处理器的优化。在这种情况下,可以根据您的特定需求重写您自己的版本(只要您的版本正确执行 =))。
  • @M.M OOps....让我再找一遍。
  • @MatteoItalia 我同意。这完全有效。我正在使用第二个实现,它需要更少的时间。但我想使用具有相同性能的预定义函数。
  • 看起来您编写了一些比预定义函数更快的代码...有时会发生这种情况。预定义函数处理各种输入情况,而您的只处理一种情况。也许你可以在 PCL 邮件列表中发布这个案例,他们的实现会进行很多函数调用(按每个点的值返回数据),也许他们认为编译器会优化它,但事实证明你的编译器没有。跨度>

标签: c++ performance point-cloud-library point-clouds c++-standard-library


【解决方案1】:

预定义函数pcl::getMinMax3D 能够通过设置优化标志并在Release 中更快。因为如果 Eigen 使用 SSE 内在函数,则操作发生在 4 个对齐的字节上。

更多信息见 https://gitter.im/PointCloudLibrary/pcl?at=5e3899d06f9d3d34981c0687

【讨论】:

    【解决方案2】:

    pcl::getMinMax3D 的实现效率非常低。要搜索最小和最大点,它会执行以下操作:

    Eigen::Array4f min_p, max_p;
    min_p.setConstant (FLT_MAX);
    max_p.setConstant (-FLT_MAX);
    for (size_t i = 0; i < cloud.points.size (); ++i)
    {
       // ... (check the validity of the point if it is not a dense cloud)
    
       pcl::Array4fMapConst pt = cloud.points[i].getArray4fMap ();
       min_p = min_p.min (pt);
       max_p = max_p.max (pt);
    }
    

    如果您检查 getArray4fMap() 函数:

    typedef Eigen::Map<Eigen::Array4f, Eigen::Aligned> Array4fMap;
    
    inline pcl::Array4fMap getArray4fMap() const { 
        return (pcl::Array4fMap(data)); 
    }
    

    对于云中的每个点,它正在构建一个Eigen::Map,然后将其与当前的最小和最大点进行比较。这是非常低效的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-03-22
      • 1970-01-01
      • 2020-06-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-02-25
      相关资源
      最近更新 更多