0

我正在CUDA机器上使用CUSP库进行稀疏矩阵乘法。我当前的代码是使用CUDA的GPU设备和零拷贝固定内存

#include <cusp/coo_matrix.h> 
#include <cusp/multiply.h> 
#include <cusp/print.h> 
#include <cusp/transpose.h> 
#include<stdio.h> 
#define CATAGORY_PER_SCAN 1000 
#define TOTAL_CATAGORY 100000 
#define MAX_SIZE 1000000 
#define ELEMENTS_PER_CATAGORY 10000 
#define ELEMENTS_PER_TEST_CATAGORY 1000 
#define INPUT_VECTOR 1000 
#define TOTAL_ELEMENTS ELEMENTS_PER_CATAGORY * CATAGORY_PER_SCAN 
#define TOTAL_TEST_ELEMENTS ELEMENTS_PER_TEST_CATAGORY * INPUT_VECTOR 
int main(void) 
{ 
    cudaEvent_t start, stop; 
    cudaEventCreate(&start); 
    cudaEventCreate(&stop); 
    cudaEventRecord(start, 0); 
    cusp::coo_matrix<long long int, double, cusp::host_memory> A(CATAGORY_PER_SCAN,MAX_SIZE,TOTAL_ELEMENTS); 
    cusp::coo_matrix<long long int, double, cusp::host_memory> B(MAX_SIZE,INPUT_VECTOR,TOTAL_TEST_ELEMENTS); 

    for(int i=0; i< ELEMENTS_PER_TEST_CATAGORY;i++){  
     for(int j = 0;j< INPUT_VECTOR ; j++){ 
      int index = i * INPUT_VECTOR + j ; 
      B.row_indices[index] = i; B.column_indices[ index ] = j; B.values[index ] = i; 
     }  
    } 
    for(int i = 0;i < CATAGORY_PER_SCAN; i++){ 
     for(int j=0; j< ELEMENTS_PER_CATAGORY;j++){  
      int index = i * ELEMENTS_PER_CATAGORY + j ; 
      A.row_indices[index] = i; A.column_indices[ index ] = j; A.values[index ] = i; 
     }  
    } 
    /*cusp::print(A); 
    cusp::print(B); */ 
    //test vector 
    cusp::coo_matrix<long int, double, cusp::device_memory> A_d = A; 
    cusp::coo_matrix<long int, double, cusp::device_memory> B_d = B; 

     // allocate output vector 
    cusp::coo_matrix<int, double, cusp::device_memory> y_d(CATAGORY_PER_SCAN, INPUT_VECTOR ,CATAGORY_PER_SCAN * INPUT_VECTOR); 
    cusp::multiply(A_d, B_d, y_d); 
    cusp::coo_matrix<int, double, cusp::host_memory> y=y_d; 
    cudaEventRecord(stop, 0); 
    cudaEventSynchronize(stop); 
    float elapsedTime; 
    cudaEventElapsedTime(&elapsedTime, start, stop); // that's our time! 
    printf("time elaplsed %f ms\n",elapsedTime); 
    return 0; 
} 

风口浪尖::乘法函数只使用1个GPU(作为我的理解)。

  1. 我该如何使用setDevice()在GPU上运行相同的程序(一个cusp :: multiply per GPU)。
  2. 准确测量总时间。
  3. 如何使用零拷贝固定内存与此库,因为我可以使用malloc自己。

回答

1

1如何使用setDevice()来同时在GPU

如果你的意思是“我怎样才能进行使用两个GPU单cusp::multiply操作”运行同一程序,得到的回答是你不能。


编辑:

对于您想运行在不同的GPU两个独立的尖点稀疏矩阵,矩阵产品的情况下,有可能在转移之前,简单地包装操作中的一个循环,并呼吁cudaSetDevicecusp::multiply呼叫。不过,你可能不会这样做,所以加快速度。我认为我的观点是正确的,即内存传输和cusp::multiply操作都阻止了呼叫,所以主CPU将停止运行直到它们完成。因此,不同GPU的调用不能重叠,并且在单个GPU上执行两次相同操作时不会加速。如果您愿意使用多线程应用程序,并且拥有一个具有多个内核的主机CPU,那么您可能仍然可以并行运行它们,但它不会像您希望的那样直接代表主机代码。

2测量的总时间准确

cuda_event方法,你现在已经是测量单个内核的执行时间的最准确的方法。如果你有一个合理的多GPU方案,那么来自每个GPU上下文的事件总和就是内核的总执行时间。如果在总时间内,指的是完成操作的“挂钟”时间,那么您需要在代码的整个multigpu部分周围使用主计时器。我隐约想起,在某些情况下,最新版本的CUDA可能会在来自不同上下文的流之间同步事件,因此基于CUDA事件的计时器可能仍然可以在这种情况下使用。

3我该如何使用zero-copy固定内存与此库,因为我可以使用malloc自己。

据我所知,这是不可能的。 CUSP使用的底层推力库可以支持使用零拷贝内存的容器,但CUSP不会公开标准矩阵构造函数中的必要机制,以便能够使用在零拷贝内存中分配CUSP稀疏矩阵。

+0

我编辑了我的问题。基本上我的意思是每个GPU 1个cusp :: multiply。 – Terminal

+0

@Terminal是你真正的问题,你实际上已经完成了这个代码的一个multigpu版本,但是你不明白为什么它需要两倍于在一个gpu上运行一次调用的时间? – talonmies

+0

其实我想知道在哪里准确使用setDevice(),以便我可以加载更多的数据并与原始数据一起运行并行矩阵乘法。 – Terminal