Как понять, что конвертировать указатель половинной точности в длинный беззнаковый длинный указатель и соответствующее выравнивание памяти? - PullRequest
1 голос
/ 22 февраля 2020

Я не знаком с проблемами выравнивания памяти и преобразования указателей. Я учусь на официальном примере кода Nvidia следующим образом.

  half *A = NULL;
  half *B = NULL;
  float *C = NULL;
  float *D = NULL;

  checkCudaErrors(cudaMalloc(reinterpret_cast<void **>(&A),
                             sizeof(half) * M_GLOBAL * K_GLOBAL));
  checkCudaErrors(cudaMalloc(reinterpret_cast<void **>(&B),
                             sizeof(half) * N_GLOBAL * K_GLOBAL));
  checkCudaErrors(cudaMalloc(reinterpret_cast<void **>(&C),
                             sizeof(float) * M_GLOBAL * N_GLOBAL));
  checkCudaErrors(cudaMalloc(reinterpret_cast<void **>(&D),
                             sizeof(float) * M_GLOBAL * N_GLOBAL));

  assert(((unsigned long long)A) % 128 == 0);
  assert(((unsigned long long)B) % 128 == 0);
  assert(((unsigned long long)C) % 128 == 0);
  assert(((unsigned long long)D) % 128 == 0);

У меня есть три вопроса к этому.

  1. Я знаю разницу между преобразованием типа указателя и числового типа преобразование. Что касается преобразования типов указателей, мы просто изменим способ понимания этого указателя. Но как понять преобразование из half* в unsigned long long*?
  2. Я думаю, что адрес памяти должен оставаться неизменным во время этого преобразования. Почему нам нужно сначала преобразовать в unsigned long long*, а затем проверить, выровнена ли память по 128?

1 Ответ

1 голос
/ 22 февраля 2020

Но как понять преобразование из half* в unsigned long long*?

В указанном вами коде нет преобразования в unsigned long long *. Существует преобразование в unsigned long long.

Целью преобразования является преобразование адреса, хранящегося в одном из A, B, C или D, в целое число, чтобы его биты могут быть исследованы. Стандарт C не определяет результат преобразования указателя в целочисленный тип, за исключением некоторых базовых c свойств, но преобразование «должно соответствовать структуре адресации среды выполнения» (C 2018 сноска 69). В компиляторе, который использует Nvidia, преобразование предположительно создает адрес, который обычно используется архитектурой процессора. Затем с помощью % 128 == 0 проверяется, совпадает ли адрес с кратным 128 байт.

Почему сначала нужно преобразовать в unsigned long long*, а затем проверить, выровнена ли память по 128?

Оператор % не будет принимать операнд-указатель, поэтому операнд должен быть преобразован в целочисленный тип, unsigned long long, а не unsigned long long *.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...