检测全局内存时的奇怪行为

时间:2013-05-22 05:38:23

标签: cuda

在阅读完这个问题:"How to differentiate between pointers to shared and global memory?"后,我决定在一个简单的测试程序中尝试isspacep.localisspacep.globalisspacep.shared

本地和共享内存的测试始终有效,但全局内存测试并不总是有效,例如,当设备代码以调试模式(-G)编译时就会发生。

起初我认为编译器检测到我使用虚拟向量作为全局内存并以不同方式处理它,因此我使用了-Xcicc -O0 -Xptxas -O0(参见"Completely disable optimizations on NVCC")。如果我使用sm_30进行计算,则会正确检测全局内存。但是,如果我使用sm_20sm_21进行计算,则不会检测到全局内存。请注意,对于-G,任何sm >= 20都有效。

我在这里缺少一些东西吗?在使用可以解释这些差异的-G时,编译器是否还有一个标志?

汇编

  

nvcc test_pointer.cu -arch = sm_20 -Xcicc -O0 -Xptxas -O0 -Xptxas -v -o test_pointer

代码

#include <stdio.h>
#include <cuda.h>

#define CUDA_CHECK_ERROR()  __cuda_check_errors(__FILE__, __LINE__)
#define CUDA_SAFE_CALL(err) __cuda_safe_call(err, __FILE__, __LINE__)

inline void __cuda_check_errors(const char *filename, const int line_number)
{
    cudaError err = cudaDeviceSynchronize();
    if(err != cudaSuccess)
    {
        printf("CUDA error %i at %s:%i: %s\n",
               err, filename, line_number, cudaGetErrorString(err));
        exit(-1);
    }
}

inline void __cuda_safe_call(cudaError err, const char *filename, const int line_number)
{
    if (err != cudaSuccess)
    {
        printf("CUDA error %i at %s:%i: %s\n",
               err, filename, line_number, cudaGetErrorString(err));
        exit(-1);
    }
}

__device__ unsigned int __isLocal(const void *ptr)
{
  unsigned int ret;
  asm volatile ("{ \n\t"
                "    .reg .pred p; \n\t"
                "    isspacep.local p, %1; \n\t"
                "    selp.u32 %0, 1, 0, p;  \n\t"
#if (defined(_MSC_VER) && defined(_WIN64)) || defined(__LP64__)
                "} \n\t" : "=r"(ret) : "l"(ptr));
#else
                "} \n\t" : "=r"(ret) : "r"(ptr));
#endif

  return ret;
}

__device__ unsigned int __isShared(const void *ptr)
{
  unsigned int ret;
  asm volatile ("{ \n\t"
                "    .reg .pred p; \n\t"
                "    isspacep.shared p, %1; \n\t"
                "    selp.u32 %0, 1, 0, p;  \n\t"
#if (defined(_MSC_VER) && defined(_WIN64)) || defined(__LP64__)
                "} \n\t" : "=r"(ret) : "l"(ptr));
#else
                "} \n\t" : "=r"(ret) : "r"(ptr));
#endif

  return ret;
}

__device__ void analyze_pointer(const void *ptr)
{
    printf("\t* is local:  %u\n", __isLocal(ptr));
    printf("\t* is global: %u\n", __isGlobal(ptr));
    printf("\t* is shared: %u\n", __isShared(ptr));
}

template <typename T, unsigned int N>
__global__ void test_kernel(T *vec)
{
    // Shared array
    __shared__ T shared_vec[10];

    // Register array
    T reg[10];

    if (blockIdx.x == 0 && threadIdx.x == 0)
    {
        printf("Register array:\n");
        analyze_pointer(&reg);

        printf("\nGlobal array:\n");
        analyze_pointer(vec);

        printf("\nShared array:\n");
        analyze_pointer(&shared_vec);
    }
}

int main()
{
    typedef float type_t;
    const unsigned int N = 128;

    type_t* d_vec;

    CUDA_SAFE_CALL(cudaMalloc(&d_vec, N * sizeof(type_t)));

    test_kernel<type_t, N><<<1, N>>>(d_vec);
    CUDA_CHECK_ERROR();

    CUDA_SAFE_CALL(cudaFree(d_vec));
}

输出

Register array:
    * is local:  1
    * is global: 0
    * is shared: 0

Global array:
    * is local:  0
    * is global: 0 (or 1 with -G or sm_30)
    * is shared: 0

Shared array:
    * is local:  0
    * is global: 0
    * is shared: 1

硬件/软件属性

使用CUDA 5.0,GeForce GT 650M(CC 3.0),Arch Linux 64位驱动程序319.17进行测试。

更新#1

我刚刚使用Tesla C2070(CC 2.0)和304.88驱动程序,Linux 64位上的CUDA 5.0测试了这段代码。关闭优化时检测到全局内存,即-arch=sm_20 -Xcicc -O0,或者添加额外printf("\t* ptr = %ld\n", ptr);时(参见@ RobertCrovella的评论)。这听起来像是司机问题。

更新#2

我做了一些测试,这是我用CC 3.0设备得到的,这取决于我如何编译程序:

-arch=sm_30                                               ---> undetected (probably optimized)
-arch=sm_30 -Xcicc -O0 -Xptxas -O0                        ---> OK
-arch=sm_30 -G                                            ---> OK
-arch=compute_30 -code=sm_30 -Xcicc -O0 -Xptxas -O0       ---> OK
-arch=compute_30 -code=sm_30 -G                           ---> OK
-arch=compute_30 -code=compute_30 -Xcicc -O0 -Xptxas -O0  ---> undetected
-arch=compute_30 -code=compute_30 -G                      ---> OK
-arch=sm_20                                               ---> undetected
-arch=sm_20 -Xcicc -O0 -Xptxas -O0                        ---> undetected
-arch=sm_20 -G                                            ---> OK
-arch=compute_20 -Xcicc -O0 -Xptxas -O0                   ---> undetected
-arch=compute_20 -G                                       ---> OK
-arch=compute_20 -code=sm_20 -Xcicc -O0 -Xptxas -O0       ---> runtime error (as expected)
-arch=compute_20 -code=sm_20 -G                           ---> runtime error (as expected)
-arch=compute_20 -code=compute_20 -Xcicc -O0 -Xptxas -O0  ---> undetected
-arch=compute_20 -code=compute_20 -G                      ---> OK
-arch=compute_20 -code=sm_30                              ---> undetected (probably optimized)
-arch=compute_20 -code=sm_30 -Xcicc -O0 -Xptxas -O0       ---> OK
-arch=compute_20 -code=sm_30 -G                           ---> OK

1 个答案:

答案 0 :(得分:1)

这显然是CUDA中的一个错误,修复程序应该与CUDA 6.0一起发布。