PointNet++等3D点云中用到的.cu、.cpp文件的编译的简单理解

简介: PointNet++等3D点云中用到的.cu、.cpp文件的编译的简单理解

1:cuda-c

Cuda-c 极大程度的方便了我们利用GPU并行处理来加快自己程序的运行速度,但是大多情况下我们的程序是一个极为庞大的工程项目,在这个项目中我们只需要利用cuda来加快其中某一块算法的运行效率,所以很多情况下利用cpp文件来调用cu中的kernel函数,从而完成程序的并行运算。虽然cuda5.0之后可以直接从vs中生成现有的cuda项目,但是利用cpp来调用cu文件的项目还是需要我们自己来进行配置的。


2:一个简单的配置流程

从一个例子先简单看一下其实现和调用过程:

1. 首先假定我们已经写好了调用gpu运算的.cu文件,如下图所示。在这个文件中,我们首先定义调用global设备函数的主函数

testghmain();


并在其前面加上extern “C” ,这个文件定义了a、b两个数组, 并利用gpu来实现c=a+b的运算。

61.png


2. 在我们的工程中,需要调用上面这个.cu文件中的函数进行并行加速的cpp文件中,对testghmain();函数进行调用,所以在文件前面需要对其进行事先声明。

  extern “C” int testghmain();

62.png

3. 之后,在上面这个.cpp文件中,需要的地方直接调用testghmain()。

63.png


在这里我们声明了一个MFC的控件响应函数OnBnClickedbutton来调用testghmain(),当用户点击这个button时,程序首先调用.cu文件中的testghmain函数,而testghmain函数会调用global设备函数,通过gpu实现c=a+b的运算,并把计算结果最终返回给用户。



3:.cu、.cpp的关系

从上面的例子中就可以看出,.cu其实就是一个函数,但是需要用cuda的命令进行编译,然后用.cpp文件进行调用里面的函数。

即:

项目中用到cuda编程,写了kernel函数,需要nvcc编译器来编译。.c/.cpp的文件,假定用gcc编译。


如何混合编译它们,整体思路是:.cu文件编译出的东西,作为最终编译出的可执行程序的链接依赖。


4:混合编译.cu、.cpp

64.png

65.png

以inux系统为例子:

1)分别编译各个文件,最后链接

nvcc -c test1.cu
gcc -c test2.c
gcc -o testc test1.o test2.o -lcudart -L/usr/local/cuda/lib64


2)将cuda编译成静态库,gcc编译cpp(不太懂)

nvcc -lib test1.cu -o libtestcu.a
gcc test2.c -ltestcu -L. -lcudart -L/usr/local/cuda/lib64


3)将cuda编译成动态库,gcc编译cpp(不太懂)

all: c
c: libtestcu.so
    gcc test2.c -ltestcu -L. -lcudart -L/usr/local/cuda/lib64 -o testc
libtestcu.so: test.cu
    nvcc -o libtestcu.so -shared -Xcompiler -fPIC test1.cu


补充:

4)将cpp编译成动态库.so

g++ -std=c++11 -shared ./3d_interpolation/tf_interpolate.cpp -o ./3d_interpolation/tf_interpolate_s


PointNet++例子:

1.将.cu文件进行编译成.o

$CUDA_ROOT/bin/nvcc ./grouping/tf_grouping_g.cu -o ./grouping/tf_grouping_g.cu.o -c -O2 -DGOOGLE_C


2.将cpp文件编译成动态库.so

g++ -std=c++11 -shared ./3d_interpolation/tf_interpolate.cpp -o ./3d_interpolation/tf_interpolate_so.s


3.将.cpp文件和.o文件编译成动态库.so

g++ -std=c++11 -shared ./grouping/tf_grouping.cpp ./grouping/tf_grouping_g.cu.o -o ./grouping/tf_grouping_so


4.python文件调用动态链接库.so

66.png


5:动态链接库(windows、linux)

在Linux上,动态库的加载机制和在Windows上完全不一样(其实应该叫做【共享库】才对,动态库是Windows的概念,Windows上为*.dll,Linux上为*.so。dll:dynamic link library,即:动态链接库。so:share object(library),即:共享库。)

1、在Windows上

一个可执行程序会先在当前目录下找需要的动态库(*.dll)文件,如果当前目录下有,则加载。如果当前目录没有,才会去系统的环境变量目录下去找,如果找到了,则加载,如果连环境变量中都找不到,将报错。


2、在Linux上

一个可执行程序会直接去 “环境变量目录下” 找共享库(*.so),如果找不到,则报错。


“环境变量目录下” 打了引号,因为这更像是一个专门用于【共享库】的环境变量,Linux的环境变量应该是PATH(可在终端输入这个查看:echo>$PATH),PATH跟Windows上的环境变量又不一样,PATH描述的是Linux命令的一个路径,而Windows上的环境变量描述的是命令+ 库。Linux的库的加载,由 /etc/ld.so.conf 和 /etc/ld.so.conf.d/*.conf 来进行加载的,不妨一个一个打开看看就一切都明白了。


6:NVCC学习笔记

见链接:https://wangpengcheng.github.io/2019/04/17/nvcc_learn_note/


7:g++的一些常用命令

1)引入头文件

当我们只编译一个main.cpp文件时输入:

g++ -o a.out main.cpp


当我们需要编译一个头文件和一个源文件如:common.h和main.cpp文件时:

假设common.h与main.cpp在同一文件夹下:

g++ -o a.out main.cpp -I .


common.h在/home/user/include文件夹下:

g++ -o a.out main.cpp -I /home/user/include/


注:可以在我提供的实例代码中发现,我在引用common.h时使用的是<common.h>其意义是去系统路径下找该文件,所以需要将目录/home/user/include/添加到此次编译的系统路径。如果是“common.h”则先在系统路径下找,再在到当前目录下找。所以如果是“common.h”,则不需要添加 -I /home/user/include/ 只写g++ -o a.out main.cpp即可。


2)编译多个源文件

当我们需要编译一个头文件和两个源文件如:common.h,common.cpp和main.cpp文件时:


g++ -o a.out main.cpp common.cpp -I /home/user/include/

3)调试

想要调试,我们需要生成具有调试信息可执行文件。

当我们需要调试上面的程序时,需要先编译,在编译时要加一个编译器参数(-g)来添加调试信息,命令如下:

g++ -g -o a.out main.cpp common.cpp -I .


4)实例

common.h:

#ifndef COMMON_H
#define COMMON_H
#include <iostream>
class A
{
public:
    void foo();
};
#endif

common.cpp:

#include <common.h>
void A::foo()
{
    std::cout<<"foo..."<<std::endl;
}


main.cpp:

#include <common.h>
int main()
{
    A a;
    a.foo();
    return 0;
}

命令行输入:

g++ -g -o a.out main.cpp common.cpp -I .
相关实践学习
基于阿里云DeepGPU实例,用AI画唯美国风少女
本实验基于阿里云DeepGPU实例,使用aiacctorch加速stable-diffusion-webui,用AI画唯美国风少女,可提升性能至高至原性能的2.6倍。
目录
相关文章
|
5月前
|
Serverless
函数计算FC的openpose用不了
函数计算FC的openpose用不了,为什么?
39 1
|
8月前
|
并行计算 算法 测试技术
[Eigen中文文档] 稠密分解方法目录
本文介绍了 Eigen 提供的处理稠密矩阵分解方法的目录。
77 0
|
6天前
ncnn中Yolov3DetectionOutput层各个参数的含义
ncnn中Yolov3DetectionOutput层各个参数的含义
8 1
|
6天前
|
计算机视觉 开发者 Python
OpenCV合并图像中加权和与覆盖的讲解与实战(附Python源码)
OpenCV合并图像中加权和与覆盖的讲解与实战(附Python源码)
103 0
|
6天前
|
运维 Serverless
函数计算FC报错问题之SDXL模型报错如何解决
函数计算(Function Compute,FC)是一个事件驱动的全托管计算服务,允许用户编写并上传代码,而无需管理服务器运行和维护;在使用过程中,可能会遇到各种报错,本合集聚焦于函数计算FC常见的报错问题,提供一系列的故障排查指导和解决建议,帮助用户优化云端函数执行
247 0
|
机器学习/深度学习 监控 计算机视觉
测试 opencv-python 中的 mat 和 Umat 处理图像的差异(GPU加速)
测试 opencv-python 中的 mat 和 Umat 处理图像的差异(GPU加速)
944 0
|
11月前
|
数据采集 传感器 编解码
点云数据处理方法的应用PCL函数库为例的设计与实现_kaic
在计算机视觉和虚拟现实技术的发展过程中,点云数据已成为主要的三维数据表达形式。将点云数据转换成灰值图时,测算每一个像素点周边领域的点云,但是其效率精密度比较低。文中探讨了点云数据的多视图拼凑和滤波处理,明确提出利用三角形面片法解决点云数据,将文件头和三角形面片信息分为两个存放,明确提出掌握坐标原点位置和方向两个核心平面反向值,点云部位转换优化算法。针对点云数据处理的相关技术研发成为近年来的研究热点,基于此,采用Python作为编程语言,并使用开源编程库Point.Cloud.Library,开发了点云数据处理系统。该系统实现了点云数据读取及数据处理、点云视点变换、重建点云效果显示等功能.
|
12月前
|
机器学习/深度学习 编解码 并行计算
432.4 FPS 快STDC 2.84倍 | LPS-Net 结合内存、FLOPs、CUDA实现超快语义分割模型(一)
432.4 FPS 快STDC 2.84倍 | LPS-Net 结合内存、FLOPs、CUDA实现超快语义分割模型(一)
129 0
|
12月前
|
并行计算 算法 数据可视化
432.4 FPS 快STDC 2.84倍 | LPS-Net 结合内存、FLOPs、CUDA实现超快语义分割模型(二)
432.4 FPS 快STDC 2.84倍 | LPS-Net 结合内存、FLOPs、CUDA实现超快语义分割模型(二)
87 0
|
算法 PyTorch 算法框架/工具
【DSW Gallery】基于EasyCV的STDC图像语义分割示例
EasyCV是基于Pytorch,以自监督学习和Transformer技术为核心的 all-in-one 视觉算法建模工具,并包含图像分类,度量学习,目标检测,姿态识别等视觉任务的SOTA算法。本文将为您介绍如何在PAI-DSW中使用EasyCV训练轻量化语义分割模型STDC
【DSW Gallery】基于EasyCV的STDC图像语义分割示例