zoukankan      html  css  js  c++  java
  • k Nearest Neighbor Search by CUDA

    kNN(k Nearest Neighbor)是常用的群集算法(Cluster Algorithm)用于空间搜索。目前最快的kNN方法莫过于KDTree的版本,不过基本上都是CPU的比如ANN C++ Library。对于GPU来说,实现加速结构比较复杂,因为没有栈所以无法递归,而且执行资源有限,不能像CPU一样舒舒服服的顺序执行。

    为了方便起见我直接用komrade粘合C++与CUDA,下面是测试程序的代码。 

    #include <komrade/device_vector.h>
    #include 
    <komrade/transform.h>
    #include 
    <komrade/range.h>
    #include 
    <komrade/copy.h>
    #include 
    <komrade/fill.h>
    #include 
    <komrade/sort.h>
    #include 
    <komrade/replace.h>
    #include 
    <komrade/functional.h>
    #include 
    <iostream>
    #include 
    <iterator>
    #include 
    <math.h>
    #include 
    <memory>
    #include 
    <boost/timer.hpp>

    using namespace std;

    #include 
    <ANN/ANN.h>
    #pragma comment(lib,"ANN.lib")

    struct dist
    {
        dist(
    float qx, float qy, float qz) : x(qx), y(qy), z(qz)
        {
        }
        
    float x,y,z;
        
        __host__ __device__ 
    float operator()(const float3& p) const
        {
            
    float a = p.x - x;
            
    float b = p.y - y;
            
    float c = p.z - z;
            
    return a*+ b*+ c*c;
        }
    };

    int main(int argc, char* argv[])
    {
        
    if( argc < 2 )
            
    return -1;
                
        
    int N = 0;
        sscanf(argv[
    1],"%d",&N);
        
        boost::timer Stopwatch;
        ANNpointArray ANNPh 
    = annAllocPts(N,3);
        komrade::host_vector
    <float3> Ph(N);
        komrade::device_vector
    <int> Idx(N);
        komrade::device_vector
    <float> Dist(N);
        
        
        
    for(int i=0; i<N; ++i)
        {
            
    float x = (float)rand() / (float)RAND_MAX;;
            
    float y = (float)rand() / (float)RAND_MAX;;
            
    float z = (float)rand() / (float)RAND_MAX;;
            
            Ph[i].x 
    = x;
            Ph[i].y 
    = y;
            Ph[i].z 
    = z;
            
            ANNPh[i][
    0= x;
            ANNPh[i][
    1= y;
            ANNPh[i][
    2= z;
                    
            
    if( N < 32 )
                printf(
    "<%f %f %f>\n",x,y,z);
            Idx[i] 
    = i;
        }
        cout
    <<fixed<<"Generate Data Used "<<Stopwatch.elapsed()<<endl;
        Stopwatch.restart();
            
        
    float QueryPos[3];
        QueryPos[
    0= (float)rand() / (float)RAND_MAX * 0.1f + 0.5f;
        QueryPos[
    1= (float)rand() / (float)RAND_MAX * 0.1f + 0.5f;
        QueryPos[
    2= (float)rand() / (float)RAND_MAX * 0.1f + 0.5f;
        
    if( N < 32 )
            printf(
    "[%f %f %f]\n",QueryPos[0],QueryPos[1],QueryPos[2]);
            
        komrade::device_vector
    <float3> Pd = Ph;
        cout
    <<fixed<<"Copy Data Used "<<Stopwatch.elapsed()<<endl;
        Stopwatch.restart();
        
        komrade::transform(Pd.begin(), Pd.end(), Dist.begin(), dist(QueryPos[
    0], QueryPos[1], QueryPos[2]));
        komrade::sort_by_key(Dist.begin(), Dist.end(), Idx.begin());
        cout
    <<fixed<<"Sort Data by CUDA Used "<<Stopwatch.elapsed()<<endl;
        Stopwatch.restart();
        
        ANNkd_tree ANNTree(ANNPh,N,
    3);
        ANNidx ANNIdx[
    1];
        ANNdist ANNDst[
    1];
        ANNTree.annkSearch(QueryPos,
    1,ANNIdx,ANNDst);
        cout
    <<fixed<<"Sort Data by ANN Used "<<Stopwatch.elapsed()<<endl;

        
        
    if( N < 32 )
        {
            copy(Dist.begin(), Dist.end(), ostream_iterator
    <float>(cout," "));
            cout
    <<endl;
            copy(Idx.begin(), Idx.end(), ostream_iterator
    <int>(cout," "));
        }
        
        
        
    return 0;
    }

    下面是性能分析对比,可以看到CUDA版本在大量点的情况下还是非常有优势的,不过在纯RenderFarm就用不上了,恐怕只能在装备有G80以上芯片的桌面环境或者工作站上执行。测试环境如下,

    • Intel E5200@2.9G
    • Apacer 2Gx2
    • 9800GT 512M
    • CUDA 2.2, komrade 0.9
      10 100 1000 10000 100000 1000000
    CUDA 0.003 0.003 0.00300 0.007 0.012 0.038
    ANN 0.000 0.000 0.00100 0.008 0.131 2.490

    CUDAKNN

    极其明显的,当排序数目数量级超过10e5的时候,CUDA显示出了巨大的速度优势。数目比较少的时候还是CPU的比较快速。

    启发自《Fast k Nearest Neighbor Search using GPU

  • 相关阅读:
    代码收藏系列--php--加载sql文件并解析成数组
    代码收藏系列--php--生成简短唯一订单号
    电子商务(电销)平台中系统设置模块(SysSetting)数据库设计明细
    电子商务(电销)平台中商品模块(Product)数据库设计明细
    电子商务(电销)平台中财务模块(Finance)数据库设计明细
    电子商务(电销)平台中内容模块(Content)数据库设计明细
    电子商务(电销)平台中用户模块(User)数据库设计明细
    电子商务(电销)平台中订单模块(Order)数据库设计明细
    sysbench性能测试详解
    mysql压力测试工具
  • 原文地址:https://www.cnblogs.com/Jedimaster/p/1497985.html
Copyright © 2011-2022 走看看