Как запросить длину строки с помощью clGetPlatformInfo (и друзей)?

Краткая версия: существует ли официальный/правильный способ запроса размера строк, таких как CL_PLATFORM_VENDOR?

Длинная версия: просмотр функций OpenCL, таких как clGetPlatformInfo Я хочу узнать, сколько места нужно выделить для результата. Функция имеет эту подпись:

cl_int clGetPlatformInfo(cl_platform_id platform,
    cl_platform_info param_name,
    size_t param_value_size,
    void *param_value,
    size_t *param_value_size_ret)

Документы говорят:

param_value_size

Specifies the size in bytes of memory pointed to by
param_value. This size in bytes must be greater
than or equal to size of return type specified in the
table below.

Все возвращаемые типы перечислены как char[]. Я хотел знать, сколько места нужно зарезервировать, поэтому я назвал это так: я передаю 0 вместо param_value_size и NULL вместо param_value, надеясь получить правильный размер в param_value_size_ret:

  size_t size = 0;
  l_success = clGetPlatformInfo(platform_id,
                                CL_PLATFORM_VENDOR, 0, NULL, &size);

  if( l_success != CL_SUCCESS)
  {
    printf("Failed getting vendor name size.\n");
    return -1;
  }
  printf("l_success = %d, size = %d\n", l_success, size);
  char* vendor = NULL;
  vendor = malloc(size);
  if( vendor )
  {
    l_success = clGetPlatformInfo(platform_id,
                                  CL_PLATFORM_VENDOR, size, vendor, &size);
    if( l_success != CL_SUCCESS )
    {
      printf("Failed getting vendor name.\n");
      return -1;
    }
    printf("Vendor name is '%s', length is %d\n", vendor, strlen(vendor));
  } else {
    printf("malloc failed.\n");
    return -1;
  }

Он вел себя так, как я надеялся, он возвращает размер 19 для строки «NVIDIA Corporation» (размер включает нулевой терминатор) и strlen возвращает 18. Это «правильный» способ запроса размера параметра или мне просто повезло? с реализацией моего поставщика? Кто-нибудь видел, как эта идиома терпела неудачу у какого-то поставщика?

Редактировать: меня смущает вот что: "Этот размер в байтах должен быть больше или равен размеру возвращаемого типа", кажется, что когда я передаю 0 и NULL, вызов должен завершиться ошибкой. потому что это не больше или равно размеру возвращаемого значения. Я не уверен, почему они говорят «тип возврата».


person Jason Dagit    schedule 20.09.2011    source источник


Ответы (2)


Да, это это правильный путь.

В тот же документ, который вы упомянули:

Если param_value имеет значение NULL, оно игнорируется.

И ниже:

Возвращает CL_SUCCESS, если функция выполнена успешно. В противном случае он возвращает следующее:

...

CL_INVALID_VALUE, если param_name не является одним из поддерживаемых значений или если размер в байтах, указанный параметром param_value_size, меньше размера возвращаемого типа, а param_value не является значением NULL.

Таким образом, даже если это не указано явно, если param_value имеет значение NULL, ошибка не должна возникать, поэтому предполагается, что код работает правильно.

Вот фрагмент кода из привязки Khronos OpenCL C++ (спецификации). Они тоже делают это таким образом, и я думаю, что это считается «официальным»:

// Specialized GetInfoHelper for STRING_CLASS params
template <typename Func>
struct GetInfoHelper<Func, STRING_CLASS>
{
    static cl_int get(Func f, cl_uint name, STRING_CLASS* param)
    {
        ::size_t required;
        cl_int err = f(name, 0, NULL, &required);
        if (err != CL_SUCCESS) {
            return err;
        }

        char* value = (char*) alloca(required);
        err = f(name, required, value, NULL);
        if (err != CL_SUCCESS) {
            return err;
        }

        *param = value;
        return CL_SUCCESS;
    }
};
person aland    schedule 20.09.2011
comment
Отличный ответ! Очень признателен. И я думаю, что использование примера Хроноса помогает. - person Jason Dagit; 21.09.2011

Обратите внимание, что в примере при запросе значения четвертый параметр должен быть NULL. В противном случае некоторые платформы возвращают CL_INVALID_VALUE.

Поскольку предварительный запрос и malloc почему-то чрезмерны, я использую один большой буфер символов в качестве обходного пути.

char vendor[10240];
l_success = clGetPlatformInfo( platform_id,
                     CL_PLATFORM_VENDOR, sizeof(vendor), vendor, NULL);
person user3567917    schedule 31.07.2014