Почему cudaPointerGetAttributes() возвращает недопустимый аргумент для указателя хоста?

Я хочу написать функцию, которая сообщает мне, является ли указатель указателем хоста или устройства. По сути, это оболочка вокруг cudaPointerGetAttributes(), которая возвращает либо 1, либо 0, независимо от того, относится ли указатель к устройству или нет.

Чего я не могу понять, так это почему cudaPointerGetAttributes не проходит проверку ошибок, возвращая недопустимый аргумент, когда я тестирую указатель хоста. Пример приведен ниже.

#include <stdio.h>
#include <stdlib.h>

#define CUDA_ERROR_CHECK(fun)                                                                   \
do{                                                                                             \
    cudaError_t err = fun;                                                                      \
    if(err != cudaSuccess)                                                                      \
    {                                                                                           \
      fprintf(stderr, "Cuda error %d %s:: %s\n", __LINE__, __func__, cudaGetErrorString(err));  \
      exit(EXIT_FAILURE);                                                                       \
    }                                                                                           \
}while(0);

int is_device_pointer(const void *ptr)
{
  int is_device_ptr = 0;
  cudaPointerAttributes attributes;

  CUDA_ERROR_CHECK(cudaPointerGetAttributes(&attributes, ptr));

  if(attributes.devicePointer != NULL)
  {
    is_device_ptr = 1;
  }

  return is_device_ptr;
}

int main()
{
  int *host_ptr, x = 0;
  int is_dev_ptr;

  host_ptr = &x;

  int *dev_ptr;
  cudaMalloc((void **)&dev_ptr, 16);

  //is_dev_ptr = is_device_pointer((const void *)host_ptr); //Causes invalid argument
  is_dev_ptr = is_device_pointer((const void *)dev_ptr);  //Works

  if(is_dev_ptr == 1)
  {
    fprintf(stdout, "Device pointer\n");
  }
  else
  {
    fprintf(stdout, "Not device Pointer\n");
  }

  CUDA_ERROR_CHECK(cudaFree((void *)dev_ptr));
  CUDA_ERROR_CHECK(cudaDeviceReset());

  return EXIT_SUCCESS;
}

person John    schedule 01.05.2018    source источник
comment
Привет. Мне было интересно, может ли кто-нибудь сказать мне, что не так с этим постом, чтобы я мог его отредактировать и улучшить? Заранее спасибо за вашу помощь.   -  person John    schedule 01.05.2018


Ответы (1)


Это ожидаемое поведение. cudaPointerGetAttributes может анализировать только те указатели, которые каким-либо образом были записаны с помощью API среды выполнения CUDA. См. документацию:

Если указатель не был выделен, отображен или зарегистрирован в контексте, поддерживающем унифицированную адресацию, возвращается cudaErrorInvalidValue.

Это говорит о том, что указатель должен быть возвращен или передан через API, такой как cudaMalloc, cudaMallocManaged, cudaHostRegister и т. д., чтобы он был «распознан» cudaPointerGetAttributes. Вы должны быть в режиме UVA, и вы должны получили указатель с помощью соответствующего метода.

В вашем случае передача голого указателя хоста таким образом не соответствует требованиям, изложенным в документации, поэтому ожидается возврат ошибки.

Этот конкретный код возврата ошибки является «нефиксированной» ошибкой CUDA, что означает, что ее можно удалить с помощью cudaGetLastError(). На мой взгляд, этот код возврата ошибки следует интерпретировать как «это обычный указатель хоста». Но, конечно, если вы передадите мусорное значение или нераспределенный указатель, вы получите тот же код ошибки.

person Robert Crovella    schedule 01.05.2018