C++可申请数组大小限制

"工作记录"

Posted by xxc on August 19, 2021

问题陈述

还是DiSCO的实验,DiSCO的预处理涉及到大量的点云转polar BEV的计算,这个过程是具有并行性的,因此之前写论文的时候用到了CUDA+Cython加速。CUDA部分是用来计算点云中每个点在polar BEV中的坐标值,C++根据CUDA中计算的坐标值将对应的点信息重新整理成polar BEV,Cython则是用来将C++的程序wrap成python中的module,整个过程就是这样。

接下来就是出现了问题。在我自己处理点云的时候,点云的规模一般在10w以下,因为是单帧的点云做Place recognition,单帧点云的规模顶多这个水平,大不了在voxelgrid 滤波一下。但是!师姐和我说跑出来Segmantation fault了,她觉得应该是点云规模太大了,70w的点不行,60w可以。我愿称师姐为测试一霸!

发现问题

首先想到的竟然是GPU难道不能支持这么多线程?我还是对GPU的能力产生了不切实际的怀疑,我的锅。

根据https://en.wikipedia.org/wiki/CUDA上的表格,我台式机RTX2060 Super的计算能力(Compute Capability)的version是7.5。对应表格中max grids per device 有 128个,对应每个grid,x维度有2147483647个thread blocks,每个blocks有1024个线程。好的,算都不用算肯定不是这个问题了。

compute-capability

那还能是啥呢,接下去看C++部分,cudaMalloc和cudaMemcpy都没报错,实际并行跑kernel程序也没问题。看来确实应该相信GPU。结果发现是在想要把数据从GPU拿回来的时候,申请了几个int [] 的问题。大概是3个 int [&{input size}],这竟然申请不下来。int 4字节,3×4×700000=8400000,8400000/1024/1024=8.011M。

这让我想到了一年前曾经支配过我的栈内存问题,像这类局部变量是在栈内存上申请的,栈内存一般也就几M,所以就会segmentation fault了。在bash中 ulimit -a可以看系统资源,我的是8192=8M,之前申请的刚好超一丢丢。所以报错了。

stack-size

解决问题

在bash中可以暂时通过 ulimit -s 来设置stack size,我将它设为 81920,就ok了。但是这只是暂时的方法,要想彻底解决这个问题,还是得从代码上,直接将所有操作放在gpu上进行计算,就不用通过c++来中间过渡了。