当迭代次数增加时,cuSparse吞吐量下降

时间:2016-11-11 00:17:11

标签: c++ matrix cuda gpu nvidia

我正在尝试通过利用尽可能多的计算资源来计算GPU用于sprase矩阵*密集向量乘法的最大吞吐量。

为了实现这个目的,我尝试了两种方法:

  1. 在主机上为x和A分配内存。在主机上存储x和A.在设备上为x和A分配内存。将x和A存储在设备上。启动计时器。在循环中通过cusparsecsrmv执行稀疏矩阵*密集向量乘法,并运行cusparsecsrmv NUM_ITERATIONS次。停止计时器。将y从设备复制到主机并检查结果的准确性。

  2. 在主机上为x和A分配内存。在主机上存储x和A.为设备上的x和A数组分配内存(即x [NUM_IMPS],A [NUM_IMPS])。将X和A存储在设备上。启动计时器。在循环中通过cusparsecsrmv执行稀疏矩阵*密集向量乘法,并在每个A [i] * x [i]上运行cusparsecsrmv NUM_IMPS次。停止计时器。将[NUM_IMPS-1]从设备复制到主机并检查结果的准确性。

  3. 以下是方法1的代码:

    // == Start timer for just measuring multiplication == 
    QueryPerformanceFrequency(&Frequency1); 
    QueryPerformanceCounter(&StartingTime1); 
    
    
    // Sparse matrix * dense vector multiplication 
    /* exercise Level 2 routines (csrmv) */ 
    for (int i = 0; i < NUM_ITERATIONS; i++) { 
    status = cusparseScsrmv(handle, CUSPARSE_OPERATION_NON_TRANSPOSE, m, n, nnz, 
    &alpha, descr, cooVal, csrRowPtr, cooColIndex, 
    &xVal[0], &beta, &y[0]); 
    } 
    
    // == End time for just measuring multiplication == 
    QueryPerformanceCounter(&EndingTime1); 
    ElapsedMicroseconds1.QuadPart = EndingTime1.QuadPart - StartingTime1.QuadPart; 
    ElapsedMicroseconds1.QuadPart *= 1000000; 
    ElapsedMicroseconds1.QuadPart /= Frequency1.QuadPart;
    

    以下是方法2的代码:

    // == Start timer for just measuring multiplication ==
    QueryPerformanceFrequency(&Frequency1);
    QueryPerformanceCounter(&StartingTime1);
    
    for (int i = 0; i < NUM_IMPS; i++) {
    status = cusparseScsrmv(handle_array[i], CUSPARSE_OPERATION_NON_TRANSPOSE, m, n, nnz,
        &alpha, descr_array[i], cooVal_array[i], csrRowPtr_array[i], cooColIndex_array[i],
        &xVal_array[i][0], &beta, &y_array[i][0]);
    }
    
    // == End time for just measuring multiplication ==
    QueryPerformanceCounter(&EndingTime1);
    ElapsedMicroseconds1.QuadPart = EndingTime1.QuadPart - StartingTime1.QuadPart;
    ElapsedMicroseconds1.QuadPart *= 1000000;
    ElapsedMicroseconds1.QuadPart /= Frequency1.QuadPart;
    

    如果NUM_ITERATIONS或NUM_IMPS = 1,则会获得相同的吞吐量。 如果NUM_IMPS = 10,则吞吐量最大化。但是,一旦NUM_IMPS = 100或更多,吞吐量就会开始减少。 与NUM_ITERATIONS类似,它开始增加,但是一旦我将NUM_ITERATIONS设置为超大数字,就说100,000吞吐量将低于NUM_ITERATIONS = 1的吞吐量。

    为什么会发生这种情况?我希望在某些时候只能让饱和度达到饱和度,而不能再高,但不会降低。

    我的想法是由于多次调用cusparsecsrmv导致GPU陷入困境,或者GPU需要冷却自身以使其速度减慢,因此吞吐量下降,但这些似乎都不是合理的结论。我

1 个答案:

答案 0 :(得分:2)

documentation:

引用
  

cuSPARSE库函数与异步执行   尊重主机并可能将控制权交还给应用程序   结果准备好之前的主机。开发人员可以使用   cudaDeviceSynchronize()函数确保执行一个   特定的cuSPARSE库例程已经完成。

除了你的计时方式,这里没有任何错误。目前,您只测量将库调用排入队列的时间,而不是测量它们运行的​​时间。一旦排队了数十或数百个操作,预计排队性能会下降是完全合理的。