为什么cuda_free的开销如此之高?(是因为调零吗?)

为什么cuda_free的开销如此之高?(是因为调零吗?),cuda,profiling,Cuda,Profiling,我观察到cudaFree操作花费的时间长得令人无法接受。为了验证它,我编写了一个简单的微基准测试代码来测试cudaFree开销。它显示出类似的趋势 第一步:cudaMallocManaged 不需要那么长时间。实际上,仅对于CudamAllocManager而言,它小于1ms 第二步:init 要初始化malloced内存区域,调用init函数。而且它也不需要少于1ms的时间 第三步:cudaFree 现在,开销出现了这需要很多时间。还有一件事越大,内存大小越长。(漂亮的线性) 问题是“为什么c

我观察到cudaFree操作花费的时间长得令人无法接受。为了验证它,我编写了一个简单的微基准测试代码来测试cudaFree开销。它显示出类似的趋势

第一步:
cudaMallocManaged
不需要那么长时间。实际上,仅对于CudamAllocManager而言,它小于1ms

第二步:
init
要初始化malloced内存区域,调用init函数。而且它也不需要少于1ms的时间

第三步:
cudaFree
现在,开销出现了这需要很多时间。还有一件事越大,内存大小越长。(漂亮的线性)

问题是“为什么cudaFree会有如此巨大的开销?它是否会因为安全问题而用零填充整个内存区域?或者它所经过的任何其他关键路径?”

这是代码和测量结果。 提前感谢:)

  • 奇怪的是,8192MB和16384MB不仅对cudaManagedMalloc和init显示小于0毫秒,而且对cudaFree显示小于0毫秒
请开导我

为什么cudaFree有这么大的开销

没有。您使用的计时方法不正确,您归因于
cudaFree
的时间来自之前的异步操作

它是否为安全问题用零填充整个内存区域

没有

或者它所走过的任何其他关键路径

不,除非它要求设备处于空闲状态,而您的情况并非如此

让我们修复代码中最明显的问题:

  // measuring initialization
  ts1 = getTimeDiff(baseTime);
  init<<<1,1>>>(dptr, num_bytes_);
  cudaDeviceSynchronize(); // Wait until the GPU is idle
  ts2 = getTimeDiff(baseTime);
您可以看到,您假设的时间是
cudaFree
是完全串行
init
内核运行所需的时间。
cudamalocmanaged
cudaFree
都会随着分配规模的增加而占用更多的时间,但这并不是不合理的

奇怪的是,8192MB和16384MB不仅对cudaManagedMalloc和init显示小于0毫秒,而且对cudaFree显示小于0毫秒

那是因为没有任何东西在运行。如果您使用correct,您将看到一切都在失败,并且出现内存不足的运行时错误

为什么cudaFree有这么大的开销

没有。您使用的计时方法不正确,您归因于
cudaFree
的时间来自之前的异步操作

它是否为安全问题用零填充整个内存区域

没有

或者它所走过的任何其他关键路径

不,除非它要求设备处于空闲状态,而您的情况并非如此

让我们修复代码中最明显的问题:

  // measuring initialization
  ts1 = getTimeDiff(baseTime);
  init<<<1,1>>>(dptr, num_bytes_);
  cudaDeviceSynchronize(); // Wait until the GPU is idle
  ts2 = getTimeDiff(baseTime);
您可以看到,您假设的时间是
cudaFree
是完全串行
init
内核运行所需的时间。
cudamalocmanaged
cudaFree
都会随着分配规模的增加而占用更多的时间,但这并不是不合理的

奇怪的是,8192MB和16384MB不仅对cudaManagedMalloc和init显示小于0毫秒,而且对cudaFree显示小于0毫秒


那是因为没有任何东西在运行。如果您使用了correct,您将看到所有操作都会失败,并且出现内存不足的运行时错误。

非常感谢您的详细回复。我不知道“cudaDeviceSynchronize()”部分。现在我看到了开销的根源。。为了确保我正确理解您的答案,主机将内核或CUDAAPI调用发送到GPU,而不管它是否实际完成。如果没有显式同步,主机就无法知道API或内核是否实际完成。默认情况下,内核是异步的。其他API可能会阻塞或异步,具体取决于API。它们都有文件记录。在这种情况下,cudaFree不是异步的,因此它会阻塞,直到设备空闲。并累计进程中运行的内核的挂钟时间。CUDA有一个名为events的工具,如果您需要它,它可以用来检测单个操作或操作组的同步、回调、计时等。再次感谢您的输入。我清楚地看到后面发生了什么。我想我也需要查找事件部分。非常感谢您的详细回复。我不知道“cudaDeviceSynchronize()”部分。现在我看到了开销的根源。。为了确保我正确理解您的答案,主机将内核或CUDAAPI调用发送到GPU,而不管它是否实际完成。如果没有显式同步,主机就无法知道API或内核是否实际完成。默认情况下,内核是异步的。其他API可能会阻塞或异步,具体取决于API。它们都有文件记录。在这种情况下,cudaFree不是异步的,因此它会阻塞,直到设备空闲。并累计进程中运行的内核的挂钟时间。CUDA有一个名为events的工具,如果您需要它,它可以用来检测单个操作或操作组的同步、回调、计时等。再次感谢您的输入。我清楚地看到后面发生了什么。我想我也需要查找事件部分。
  // measuring initialization
  ts1 = getTimeDiff(baseTime);
  init<<<1,1>>>(dptr, num_bytes_);
  cudaDeviceSynchronize(); // Wait until the GPU is idle
  ts2 = getTimeDiff(baseTime);
$ nvcc -std=c++11 -o fliestime fliestime.cu 

$ ./fliestime 
sizeof(size_t): 8
sizeof(unsigned int): 4
sizeof(int): 4
sizeof(long): 8
cudaMallocManaged, memory_size:1MB, duration:102
init, memory_size:1MB, duration:2
cudaFree, memory_size:1MB, duration:1

cudaMallocManaged, memory_size:2MB, duration:0
init, memory_size:2MB, duration:5
cudaFree, memory_size:2MB, duration:0

cudaMallocManaged, memory_size:4MB, duration:1
init, memory_size:4MB, duration:8
cudaFree, memory_size:4MB, duration:0

cudaMallocManaged, memory_size:8MB, duration:1
init, memory_size:8MB, duration:17
cudaFree, memory_size:8MB, duration:1

cudaMallocManaged, memory_size:16MB, duration:1
init, memory_size:16MB, duration:33
cudaFree, memory_size:16MB, duration:1

cudaMallocManaged, memory_size:32MB, duration:3
init, memory_size:32MB, duration:65
cudaFree, memory_size:32MB, duration:2

cudaMallocManaged, memory_size:64MB, duration:5
init, memory_size:64MB, duration:121
cudaFree, memory_size:64MB, duration:4

cudaMallocManaged, memory_size:128MB, duration:9
init, memory_size:128MB, duration:219
cudaFree, memory_size:128MB, duration:8

cudaMallocManaged, memory_size:256MB, duration:17
init, memory_size:256MB, duration:427
cudaFree, memory_size:256MB, duration:18

cudaMallocManaged, memory_size:512MB, duration:34
init, memory_size:512MB, duration:854
cudaFree, memory_size:512MB, duration:35

cudaMallocManaged, memory_size:1024MB, duration:67
init, memory_size:1024MB, duration:1709
cudaFree, memory_size:1024MB, duration:70

cudaMallocManaged, memory_size:2048MB, duration:133
init, memory_size:2048MB, duration:3418
cudaFree, memory_size:2048MB, duration:141

cudaMallocManaged, memory_size:4096MB, duration:786
init, memory_size:4096MB, duration:4
cudaFree, memory_size:4096MB, duration:0

cudaMallocManaged, memory_size:8192MB, duration:0
init, memory_size:8192MB, duration:0
cudaFree, memory_size:8192MB, duration:0

cudaMallocManaged, memory_size:16384MB, duration:0
init, memory_size:16384MB, duration:0
cudaFree, memory_size:16384MB, duration:0