繁体   English   中英

CUDA 将错误显示为矩阵的“无效参数” - 乘以 N 次

[英]CUDA shows error as "Invalid Argument" for matrix - multiplication of N times

我正在尝试将矩阵 A(n 次)与矩阵 B 相乘。我使用内核进行矩阵乘法并使用流进行 N 次乘法。 因此,我有 3 个条件要测试。 我的第一个条件运行成功。

我不知道为什么它在第二次条件迭代中显示“无效参数”错误。 我猜我没有正确清理我的记忆。 我已尽力释放所有主机和设备变量。 还尝试了 CUDA 设备重置,没有任何帮助。 谁能帮我调试一下?

请在这里找到我的代码部分:

int main(){
    
    
    for (int i = 0; i < 3; i++) {
        
      
      for (int ind = 0; ind < itr; ind++){
          cudaStreamCreate(&(stream[ind]));
      }
      cudaCheckErrors("cudaStreamCreate fail");

      for (int ind = 0; ind < itr; ind++){
          cudaMemcpyAsync(d_a[ind], h_a[ind], bytes_a, cudaMemcpyHostToDevice, stream[ind]);
      }
      cudaDeviceSynchronize();

      for (int ind = 0; ind < itr; ind++){
          // Launch our kernel
          matrixMul<<<BLOCKS, THREADS, 0, stream[ind]>>>(d_a[ind], b, d_c[ind], M, K, N);
      }
      cudaDeviceSynchronize();
      cudaCheckErrors("kernel fail");

      for (int ind = 0; ind < itr; ind++){
          cudaMemcpyAsync(h_c[ind], d_c[ind], bytes_c, cudaMemcpyDeviceToHost, stream[ind]);
      }

      for (int ind = 0; ind < itr; ind++){
          cudaStreamSynchronize(stream[ind]);
      }
        
      cudaEventRecord( stop, 0 );
      cudaEventSynchronize( stop );

      cudaEventDestroy( start );
      cudaEventDestroy( stop);

      // Free allocated memory ****The issue was here.******
      cudaFreeHost(h_a);
      cudaFree(b);
      cudaFreeHost(h_c);
      cudaFree(d_a);
      cudaFree(d_c);
      cudaDeviceReset();
    }

    return 0;
}

在第二次迭代中,我收到错误消息:

Fatal error: cudaStreamCreate fail (invalid argument at /tmp/tmpwgpzgk9m/73a7502c-7662-4e80-804e-4debff15dc45.cu:140)
*** FAILED - ABORTING

解决了:

由于内存泄漏而出现错误。 我正在分配数组指针,但只释放了第一个指针。 根据罗伯特的以下回答的建议,内存应该用于数组的每个索引。 并且请始终像这样在 cuda 中使用正确的错误

.

建议:实施适当的 CUDA 错误检查 在每次 cuda 调用中使用它。 您对错误检查宏的随意使用会导致令人困惑的输出,这似乎表明流创建存在问题。

事实并非如此。 无效参数是由您在循环结束时的释放操作引起的。 你有很多错误:

  1. 我们不会在malloc返回的指针或实际上是堆栈数组的指针上使用cudaFreeHost
  2. 您不会在实际上是堆栈数组的指针上使用cudaFree
  3. 如果您在循环中进行了分配,则可能必须在循环中进行自由操作。
  4. 即使您使用了cudaDeviceReset (无论如何都会释放所有设备分配),由于malloc分配的释放不当,您cudaDeviceReset出现内存泄漏。

通过如下修改代码的结尾:

  ...
  cudaEventDestroy( start );
  cudaEventDestroy( stop);

  for (int ind = 0; ind < itr; ind++){
      free(h_a[ind]);
      free(h_c[ind]);
      cudaFree(d_a[ind]);
      cudaFree(d_c[ind]);
  }
  // Free allocated memory
  cudaFree(b);
  cudaDeviceReset();
}
...

我能够使上述错误消失。

顺便说一句,应该没有必要创建 5000 个流,但它似乎可以工作,所以我将保留它。 我通常会建议流重用。

流重用可能看起来像这样。 与其创建 5000 个流,不如选择一个较小的数字,例如 5(此处确切的数字应该无关紧要。很可能在 3 或更大范围内的任何内容的行为都会相似)。

  1. 创建那么多流:

     const int max_streams = 5; for (int ind = 0; ind < max_streams; ind++){ cudaStreamCreate(&(stream[ind])); }
  2. 在使用流时,使用模算术在流中“旋转”:

     for (int ind = 0; ind < itr; ind++){ cudaMemcpyAsync(d_a[ind], h_a[ind], bytes_a, cudaMemcpyHostToDevice, stream[ind%max_streams]); } cudaDeviceSynchronize(); for (int ind = 0; ind < itr; ind++){ // Launch our kernel matrixMul<<<BLOCKS, THREADS, 0, stream[ind%max_streams]>>>(d_a[ind], b, d_c[ind], M, K, N); } cudaDeviceSynchronize(); ...

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM