• 【点云处理】点云法向量估计及其加速(4)


        上篇文章【点云处理】点云法向量估计及其加速(3)介绍了如何使用pcl提供的gpu版本法向量计算接口对点云发向量计算进行加速。不足之处在于点云k近邻查找依然比较耗时,成为影响整体计算性能的瓶颈。这篇文章就如何优化点云K近邻查找效率进行实验。上一篇文章的示例代码中knn算法实际上主要是分为两个部分:1).KDTree建树;2).根据建好的KDTree做k近邻搜索,从而建立k近邻表。

    1. for (auto i=0; i
    2. kdtree->nearestKSearch(cloud->points[i], 10, neighbors_all[i], dists);
    3. sizes[i] = neighbors_all[i].size();
    4. }

    我们应该注意到,k近邻搜索这一步我们只是简简单单使用了一个for循环进行逐个点云的搜索,完全没有考虑到这一查找过程的可并行性,所以这里我们首先尝试使用多线程对这一过程进行提速。当我们考虑多线程时可以使用boost::thread库或者自从C++ 11开始支持的std::thread,也可以使用操作系统相关的线程API,如在Linux上,可以使用pthread库。除此之外,还可以使用omp来使用多线程。它的好处是跨平台,使用简单。这里直接使用OpenMP提供的parallel编译指示命令"#pragma omp parallel for"来告诉编译器对后面的for并行执行。编译器会创建一个包含N(在运行时决定,通常为服务器的逻辑核数)个线程的先成组,由他们来并行地运行后面的for语句块。

    1. # pragma omp parallel for
    2. for (auto i=0; i
    3. std::vector<float> dists;
    4. kdtree->nearestKSearch(cloud->points[i], 10, neighbors_all[i], dists);
    5. sizes[i] = neighbors_all[i].size();
    6. }

    ok,再次编译运行。

    提速明显,从处理器的资源利用来看每个核都分担了压力。

                                                                                     图:无omp加速

                                                                                      图:有omp加速 

    通过简单调试也可以证实是用上了,因为结果是乱序的。

    1. 28 # pragma omp parallel for
    2. 29 for (auto i=0; i
    3. 30 std::vector<float> dists;
    4. 31 kdtree->nearestKSearch(cloud->points[i], 10, neighbors_all[i], dists);
    5. 32 sizes[i] = neighbors_all[i].size();
    6. 33 printf("point[%d] is processing...\n", i);
    7. 34 }

    point[53295] is processing...
    point[21318] is processing...
    point[42636] is processing...
    point[31977] is processing...
    point[53296] is processing...
    point[21319] is processing...
    point[53297] is processing...
    point[31978] is processing...
    point[21320] is processing...
    point[53298] is processing...

    【补充:我项目中用到的CMakeLists.txt】

    1. cmake_minimum_required(VERSION 3.0.2)
    2. project(calc_normal)
    3. ### Compile as C++14, supported in ROS Kinetic and newer
    4. add_compile_options(-std=c++14)
    5. SET(CMAKE_BUILD_TYPE RELEASE CACHE STRING "Set build type release" FORCE)
    6. option(USE_DEBUG "Debug Code" OFF)
    7. option(USE_OPENMP "Use OpenMP" ON)
    8. if(USE_DEBUG)
    9. add_definitions(-DUSE_DEBUG)
    10. endif()
    11. if(USE_OPENMP)
    12. find_package(OpenMP REQUIRED)
    13. if(${OPENMP_FOUND})
    14. message("Find OpenMP")
    15. set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}")
    16. set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}")
    17. set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${OpenMP_EXE_LINKER_FLAGS}")
    18. endif()
    19. endif(USE_OPENMP)
    20. find_package(CUDA REQUIRED)
    21. find_package(PCL 1.11 REQUIRED)
    22. if(NOT ${PCL_FOUND})
    23. message("PCL 1.11 Not Found ...Searching 1.12")
    24. find_package(PCL 1.12 REQUIRED)
    25. endif(NOT ${PCL_FOUND})
    26. message("PCL_INCLUDE_DIRS" ${PCL_INCLUDE_DIRS})
    27. include_directories(${PCL_INCLUDE_DIRS})
    28. message("PCL_LIBRARY_DIRS" ${PCL_LIBRARY_DIRS})
    29. link_directories(${PCL_LIBRARY_DIRS})
    30. add_definitions(${PCL_DEFINITIONS})
    31. find_package(catkin REQUIRED COMPONENTS
    32. roscpp
    33. std_msgs
    34. message_generation
    35. sensor_msgs
    36. )
    37. catkin_package(
    38. CATKIN_DEPENDS
    39. message_runtime
    40. )
    41. if(CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64")
    42. message("embed_platform on")
    43. include_directories(${CUDA_INCLUDE_DIRS})
    44. link_directories(/usr/local/cuda/targets/aarch64-linux/lib)
    45. link_directories(/usr/local/cuda/lib64)
    46. set(CUDA_GEN_CODE "-gencode=arch=compute_72,code=sm_72")
    47. set(CUDA_NVCC_FLAGS "${CUDA_NVCC_FLAGS} ${CUDA_GEN_CODE}")
    48. else()
    49. message("embed_platform off")
    50. include_directories(${CUDA_INCLUDE_DIRS})
    51. link_directories(/usr/local/cuda/lib64)
    52. set(CUDA_GEN_CODE "-gencode=arch=compute_75,code=sm_75")
    53. set(CUDA_NVCC_FLAGS "${CUDA_NVCC_FLAGS} ${CUDA_GEN_CODE}")
    54. endif()
    55. include_directories(
    56. ${catkin_INCLUDE_DIRS}
    57. )
    58. file(GLOB_RECURSE PROJECT_SRC
    59. ./src/*.cpp
    60. )
    61. cuda_add_executable(${PROJECT_NAME} src/main.cpp ${PROJECT_SRC})
    62. ## Specify libraries to link a library or executable target against
    63. target_link_libraries(${PROJECT_NAME} cudart)
    64. target_link_libraries(${PROJECT_NAME} ${catkin_LIBRARIES})
    65. target_link_libraries(${PROJECT_NAME} ${PCL_LIBRARIES})
    66. if(USE_OPENMP)
    67. if(${OpenMP_FOUND})
    68. target_link_libraries(${PROJECT_NAME} OpenMP::OpenMP_CXX)
    69. endif()
    70. endif(USE_OPENMP)

  • 相关阅读:
    java计算机毕业设计springboot+vue居民社区健康管理平台
    VoLTE基础自学系列 | VoLTE呼叫流程之VoLTE打VoLTE,主被叫接入域为LTE
    类和对象(上)
    轧钢切头飞剪机设计及有限元分析
    【es5】标准库
    WM_COPYDATA传回返回值的一个方案
    老照片怎么修复清晰?轻松几步让图片焕发新生
    MySQL 数据的基本操作:插入、修改、删除和清空数据(详解)
    vue的一些总结
    通过Oracle Enterprise Manager管理OCI上的ADG
  • 原文地址:https://blog.csdn.net/ChuiGeDaQiQiu/article/details/127854198