【问题标题】:opencv for-loop with CUDA - parallel processing带有CUDA的opencv for-loop - 并行处理
【发布时间】:2012-10-27 08:05:08
【问题描述】:

我遇到了一个问题,就是让这个迭代器循环在 CUDA 上工作。 有人可以帮忙吗?

std::vector<cv::DMatch>  matches;
std::vector<cv::KeyPoint> key_pts1, key_pts2;
std::vector<cv::Point2f> points1, points2;
for (std::vector<cv::DMatch>::const_iterator itr = matches.begin(); itr!= matches.end(); ++it) 
        {                   
            float x = key_pts1[itr->queryIdx].pt.x;
            float y = key_pts1[itr->queryIdx].pt.y;
            points1.push_back(cv::Point2f(x,y));                
            x = key_pts2[itr->trainIdx].pt.x;
            y = key_pts2[itr->trainIdx].pt.y;
            points2.push_back(cv::Point2f(x,y));            
        }

上述转换为 CUDA - 并行处理,我认为这对我来说似乎相当困难。

void dmatchLoopHomography(float *itr, float *match_being, float *match_end, float      *keypoint_1, float *keypoint_2, float *pts1, float *pts2)
{
float x, y;
// allocate memory in GPU memory
unsigned char *mtch_begin, *mtch_end, *keypt_1, *keypt_2, points1, *points2; 
cudaHostGetDevicePointer(&mtch_begin, match_being, 0);
cudaHostGetDevicePointer(&mtch_end, match_end, 0);
cudaHostGetDevicePointer(&keypt_1, keypoint_1, 0);
cudaHostGetDevicePointer(&keypt_2, keypoint_2, 0);
cudaHostGetDevicePointer(&points1, pts1, 0);
cudaHostGetDevicePointer(&points2, pts2, 0);

//dim3 blocks(16, 16); 
dim3 threads(itr, itr); 
//kernal
dmatchLoopHomography_ker<<<itr,itr>>>(mtch_begin, mtch_end, keypt_1, keypt_2, points1. points2)
cudaThreadSynchronize();    
}

 __global__ void dmatchLoopHomography_ker(float *itr, float *match_being, float *match_end, float *keypoint_1, float *keypoint_2, float *pts1, float *pts2)
{
 //how do I go about it ??
}

【问题讨论】:

    标签: c++ opencv cuda parallel-processing nvidia


    【解决方案1】:

    首先,我注意到您的程序包括将vector&lt;KeyPoint&gt; 移动到vector&lt;Point2f&gt; 结构中。 OpenCV 有一个非常好的单行代码可以为您执行此操作:

    using namespace cv;
    KeyPoint::convert(key_pts1, points1); //vector<KeyPoint> to vector<Point2f>
    

    现在,让我们谈谈 GPU 方面的内容。事实证明cudaHostGetDevicePointer() 没有分配内存。您需要cudaMalloc() 来分配内存。例如:

    //compile with nvcc, not gcc
    float* device_matches;
    int match_length = matches.end() - matches.begin();
    cudaMalloc(&device_matches, match_length*sizeof(float));
    //do the same as above for key_pts1, key_pts2, points1, and points2
    

    现在,device_matches 只是一个普通的 C 数组,而不是 STL 向量。所以,你没有迭代器。相反,您必须只使用普通的数组索引。如果您真的想在 GPU 上使用迭代器,请查看 Thrust library。 Thrust 确实很方便,但缺点是 Thrust 只提供了一组特定的预烘焙函数。


    更大的问题是您是否想在 GPU 上执行程序的这个特定部分。我建议将 GPU 用于真正计算密集型的东西(例如,实际的特征匹配),但在数据格式之间移动数据(如您的示例代码)比特征匹配便宜许多数量级。

    另外,请记住,您在 GPU 上的数据结构通常与在 CPU 上的结构不同。这种重组不一定在计算上很昂贵,但你会想留出一些时间在白板上解决它,扯掉你的头发等等。最后,如果你对 GPU 的东西很认真,那么它可能值得工作通过一些简单的 GPU 编程示例(我很喜欢 Dr. Dobbs Supercomputing for the Masses tutorials),参加 GPU/并行课程,或者与一些 GPU 黑客朋友交谈。

    【讨论】:

    • 感谢 @solvingPuzzles 的回答和 cmets。是的,我同意您的观点,即特征匹配具有更高的计算要求。我提出问题的目的是了解如何解决这个简单的问题,然后我可以从我学习 GPU 期间获得的信息中获得 GPU 上的特征匹配。感谢您与 Dr.Dobbs 的链接。是的,我也一直在努力研究它。顺便说一句,感谢 keypoint::convert,以前知道...
    • @timothy 不错!作为一个玩具示例,我建议在 CUDA 中编写矩阵乘法。随意“作弊”并查看示例代码。这段代码不会很冗长,但你会学到样板的 CUDA 东西(threadIdxblockIdxcudaMemcpygridblock 等)
    猜你喜欢
    • 1970-01-01
    • 2012-06-23
    • 1970-01-01
    • 2018-06-06
    • 2012-06-26
    • 1970-01-01
    • 1970-01-01
    • 2021-02-01
    • 2016-08-08
    相关资源
    最近更新 更多