我正在Jetson TK1上开发一个OpenCV应用程序。我正在使用NVIDIA提供的OpenCV4Tegra软件包。
dpkg -l输出:
ii libopencv4tegra 2.4.10.1 armhf OpenCV4Tegra
ii libopencv4tegra-dev 2.4.10.1 armhf OpenCV4Tegra
ii libopencv4tegra-repo 2.4.10.1 armhf OpenCV4Tegra
我试图了解Jetson可以为我的应用程序提供的加速。
我已经测试过将数据从主机复制到设备。
OpenCV代码:
cv::Mat src_host = cv::imread("image.png");
cv::gpu::GpuMat src;
src.upload(src_host);
我已将上传调用置于循环中并计时。它通常平均约为10毫秒。
当我尝试类似的Cuda代码时:
cv::Mat src_host = cv::imread("image.png");
int nb_bytes = src_host.rows*src_host.cols*src_host.elemSize1();
uchar* data;
cudaMalloc(&data, nb_bytes);
cudaMemcpy(data, src_host.data, nb_bytes, cudaMemcpyHostToDevice);
此代码平均约为50-100us。
当我尝试OpenCV操作时:
cv::gpu::GaussianBlur(src, dst, cv::Size(25, 25), 0);
这比定制的Cuda实现还要长一个数量级。
我是否正确使用OpenCV的gpu功能?我做出了错误的假设吗?
答案 0 :(得分:4)
如果使用nvvp启动代码,您将看到opencv在您可以在设备上执行的每项操作后调用cudaDeviceSynchronize。
要避免这些同步,您必须通过创建gpu :: Stream并将您的操作启动到流中来使用其异步API。
请不要忘记在所有内核调用之后再进行一次同步。
您还可以注意到,对于某些操作(erode / dilate / GaussianBlur / ...),第一次调用的时间比其他操作要长很多,以避免在设备初始化期间调用它们一次以便进行基准测试你的代码正好在你之后。