OpenCL - Как запросить ширину SIMD устройства?
В CUDA существует концепция warp, которая определяется как максимальное количество потоков, которые могут выполнять одну и ту же команду одновременно в пределах одного обрабатывающего элемента. Для NVIDIA этот размер основы составляет 32 для всех своих карт, которые в настоящее время находятся на рынке.
В карточках ATI существует аналогичная концепция, но терминология в этом контексте - волновой фронт. После некоторой охоты, я узнал, что карта ATI у меня имеет размер волнового фронта 64.
Мой вопрос: что я могу сделать для запроса этой ширины SIMD во время выполнения для OpenCL?
Ответы
Ответ 1
Я нашел ответ, который искал. Оказывается, вы не запрашиваете устройство для этой информации, вы запрашиваете объект ядра (в OpenCL). Мой источник:
http://www.hpc.lsu.edu/training/tutorials/sc10/tutorials/SC10Tutorials/docs/M13/M13.pdf
(Страница 108)
который гласит:
Наиболее эффективные размеры рабочих групп, вероятно, будут иметь кратность собственной ширины выполнения оборудования
- размер волнового фронта в AMD говорят/размер warp в Nvidia говорят
- Устройство запросов для CL_KERNEL_PREFERRED_WORK_GROUP_SIZE_MULTIPLE
Итак, короче говоря, ответ заключается в вызове метода clGetKernelWorkGroupInfo() с именем параметра CL_KERNEL_PREFERRED_WORK_GROUP_SIZE_MULTIPLE. См. Эту ссылку для получения дополнительной информации об этом методе:
http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/clGetKernelWorkGroupInfo.html
Ответ 2
В AMD вы можете запросить CL_DEVICE_WAVEFRONT_WIDTH_AMD. Это отличается от CL_DEVICE_SIMD_WIDTH_AMD, который возвращает количество потоков, которые он выполняет в каждом такте. Последнее может быть меньше размера волнового фронта, и в этом случае для выполнения одной команды для всех потоков в волновом фронте требуется несколько тактовых циклов.
Ответ 3
В NVIDIA вы можете запросить ширину размера warp, используя clGetDeviceInfo с CL_DEVICE_WARP_SIZE_NV (хотя это всегда 32 для текущих графических процессоров), однако это расширение, поскольку OpenCL не определяет ничего, как перекосы или волновые фронты. Я не знаю о каких-либо расширениях AMD, которые позволяли бы запрашивать размер волнового фронта.
Ответ 4
Для AMD: clGetDeviceInfo (..., CL_DEVICE_WAVEFRONT_WIDTH_AMD,...) (если поддерживается расширение cl_amd_device_attribute_query)
Для Nvidia: clGetDeviceInfo (..., CL_DEVICE_WARP_SIZE_NV,...) (если поддерживается расширение cl_amd_device_attribute_query)
Но существует без единого пути. Способ, предложенный Джонатаном Декарло, не работает, я использовал его для графических процессоров, если эти два расширения не поддерживаются - например, Intel iGPU, но в последнее время я столкнулся с неправильными результатами на Intel HD 4600:
Intel HD 4600 говорит CL_KERNEL_PREFERRED_WORK_GROUP_SIZE_MULTIPLE = 32, в то время как на самом деле графические процессоры Intel, похоже, имеют волновой фронт, равный 16, поэтому я столкнулся с неправильными результатами, все работает отлично, если были использованы барьеры для волнового фронта = 16.
P.S. У меня недостаточно репутации, чтобы комментировать ответ Джонатана Декарло об этом, будем рады, если кто-то добавит комментарий.
Ответ 5
Вы можете использовать clGetDeviceInfo для получения максимального количества рабочих элементов, которые вы можете иметь в своем локальном рабочем наборе для каждого измерения. Это, скорее всего, кратное вашему размеру волнового фронта.
Смотрите: http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/clGetDeviceInfo.html
Ответ 6
Для CUDA (с использованием NVIDIA) ознакомьтесь с B.4.5 Руководством по программированию Cuda от NVIDIA. Для хранения этой информации существует переменная. Вы можете запросить эту переменную во время выполнения. Для AMD я не уверен, есть ли такая переменная.