【问题标题】:Why is my CUDA kernel returning old values?为什么我的 CUDA 内核返回旧值?
【发布时间】:2015-04-24 18:28:25
【问题描述】:

我几乎要为这个问题扯掉头发了。

我有一个 CUDA 内核,它对存储在 3D 数组中的数据进行一些数学运算。在测试这个时,我曾经为数组分配一些值(非零)并观察结果。从那以后,我注释掉了这些行,但结果仍然相同。就好像它完全忽略了我正在将 memset 设置为 0 的事实。

当我在 Debug 中单步执行代码时,代码可以正常工作...但在 Release 中却不行! 我的猜测是这个矩阵有内存泄漏。

我将此数组分配为:

cudaExtent m_extent = make_cudaExtent(sizeof(float)*matdim.x, matdim.y, matdim.z); // width, height, depth
cudaPitchedPtr m_device;
cudaMalloc3D(&m_device, m_extent);
cudaMemset3D(m_device, 0, m_extent);

我这样循环调用内核:

for (int iter = 0; iter < gpu_iterations; iter++)
    {
        PF_iteration_kernel<<<grids,threads>>>(m_device, m_extent, matdim);
        cudaDeviceSynchronize(); 
    }

之后我释放m_device 倾斜指针:

cudaFree(m_device.ptr);

matdim 只是一个 dim3 持有的矩阵维度。

在内核中,我执行以下操作(好吧,我将所有功能都注释掉了......):

__global__ void PF_iteration_kernel(cudaPitchedPtr mPtr, cudaExtent mExt, dim3 matrix_dimensions)
{
int x = threadIdx.x + blockIdx.x * blockDim.x;
int y = threadIdx.y + blockIdx.y * blockDim.y;

// Find location within the pitched memory
char *m = (char*)mPtr.ptr;

int sof = sizeof(float);
size_t pitch = mPtr.pitch;
size_t slice_pitch = pitch*mExt.height;
char* m_addroff = m + y * pitch + x * sof;
printf("m(%d,%d) is %f \n", x, y, *m_addroff); // display the slice

*m_addroff = 0; // WILL THIS RESET IT?!

__syncthreads();
}

这应该只是显示 0,但它显示了我的旧值(25、26、27、28 等)。

我已经多次清理、重新清理和重建所有东西。我已经重新启动了 IDE。

我的 IDE 是带有 NSight 4.6 (CUDA 7.0) 的 Visual Studio 2010。 我在 Windows 7 x64 上

【问题讨论】:

  • 这个之前的 SO 问题有什么相关性吗? stackoverflow.com/questions/10611451/…
  • @WeatherVane,我不这么认为。接受的答案甚至不会释放他们分配的任何内存。我所做的只是一个 Malloc 和一个 Memset,但另一个问题中的人也在询问 Memcpy。
  • printf("m(%d,%d) is %f \n", x, y, *m_addroff); 中,编译器肯定会看到char 并将其提升为int 并推入堆栈——而不是将float 提升为格式要求的double?因为 char* m_addroff 不是 float 并且编译器不会根据格式规范推送 args - 尽管有些编译器会警告问题。
  • 有趣!我想我必须在尝试 printf() 之前将 m_addroff 类型转换为浮动。否则它必须使用一些旧值?我觉得奇怪的是它找到了一些以前的值来显示。但是,嘿,如果它有效,它就有效。谢谢@WeatherVane :) 如果您想将其发布为答案,我会接受。 (哇……)

标签: c++ c cuda


【解决方案1】:

考虑一下

char* m_addroff = m + y * pitch + x * sof;
printf("m(%d,%d) is %f \n", x, y, *m_addroff);

编译器将看到 char 并将其提升为 int 并推入堆栈 - 而不是格式要求的 float 提升为 double

编译器不提供符合格式规范的参数,但一些编译器会检查格式规范并警告问题。

我建议你提出论点。我冒着猜测和失败的风险,但是像这样

printf("m(%d,%d) is %f \n", x, y, *(float*)m_addroff);

这是一个简单的例子。

#include <stdio.h>
int main()
{
    char car [4] = {0};
    char *cptr = car;
    printf ("Hello %f\n", *(float*)cptr);
    return 0;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-03-27
    • 2021-05-30
    • 2014-03-14
    • 1970-01-01
    • 2012-10-28
    • 2017-01-15
    • 1970-01-01
    • 2016-01-16
    相关资源
    最近更新 更多