У меня есть некоторые вопросы, висящие в воздухе без ответа в течение нескольких дней. Вопросы возникли из-за того, что у меня есть OpenMP и OpenCL-реализации одной и той же проблемы. OpenCL отлично работает на GPU, но на 50% меньше производительности при работе на процессоре (по сравнению с реализацией OpenMP). A post уже имеет дело с разницей между OpenMP и OpenCL, но это не отвечает на мои вопросы. На данный момент я сталкиваюсь с этими вопросами:
1) Действительно ли важно иметь " векторное ядро " (с точки зрения Intel Offline Compiler)?
Существует подобный пост, но я думаю, что мой вопрос более общий.
Как я понимаю: векторизованное ядро не обязательно означает, что в скомпилированном двоичном файле нет команды vector/SIMD. Я проверил ассемблерные коды моих ядер, и есть куча инструкций SIMD. Векторное ядро означает, что с помощью инструкций SIMD вы можете выполнять 4 (SSE) или 8 (AVX) OpenCL "логических" потоков в одном потоке процессора. Это может быть достигнуто только в том случае, если ВСЕ ваши данные последовательно хранятся в памяти. Но у кого есть такие отлично отсортированные данные?
Итак, мой вопрос: действительно ли важно, чтобы ваше ядро "векторизовало" в этом смысле?
Конечно, это дает повышение производительности, но если большая часть вычислительных массивов в ядре выполняется векторными инструкциями, вы можете приблизиться к "оптимальной" производительности. Я думаю, что ответ на мой вопрос заключается в пропускной способности памяти. Вероятно, векторные регистры лучше подходят для эффективного доступа к памяти. В этом случае аргументы ядра (указатели) должны быть векторизованы.
2) Если я выделить данные в локальной памяти на ЦП, где это будет выделено? OpenCL показывает кеш L1 как локальную память, но, очевидно, это не тот же тип памяти, что и в локальной памяти GPU. Если он хранится в ОЗУ/глобальной памяти, тогда нет смысла копировать в него данные. Если бы он был в кеше, какой-то другой процесс мог бы вывести его из строя... так что это тоже не имеет смысла.
3) Как "логические" потоки OpenCL сопоставляются с реальными потоками программного обеспечения/аппаратного обеспечения Intel (Intel HTT)? Поскольку, если у меня есть короткие ядра и ядра раздвоены, как в TBB (Блоки Thread Building) или OpenMP, тогда преобладают служебные данные fork.
4) Что такое поток fork накладные расходы? Появляются ли новые потоки процессора для любых "логических" потоков OpenCL или потоки CPU, раздвоенные один раз и повторно используемые для более "логических" потоков OpenCL?
Надеюсь, что я не единственный, кто интересуется этими крошечными вещами, и некоторые из вас могут теперь немного решить эти проблемы. Заранее благодарю вас!
UPDATE
3) В настоящее время служебные данные OpenCL более значимы, чем OpenMP, поэтому для эффективного выполнения во время выполнения требуются тяжелые ядра. В Intel OpenCL рабочая группа сопоставляется с потоком TBB, поэтому 1 виртуальное ядро процессора выполняет целую рабочую группу (или блок потоков). Рабочая группа реализована с 3-мя вложенными циклами, где, если это возможно, векторизован внутренний цикл. Поэтому вы могли бы представить себе что-то вроде:
#pragam omp parallel for
for(wg=0; wg < get_num_groups(2)*get_num_groups(1)*get_num_groups(0); wg++) {
for(k=0; k<get_local_size(2); k++) {
for(j=0; j<get_local_size(1); j++) {
#pragma simd
for(i=0; i<get_local_size(0); i++) {
... work-load...
}
}
}
}
Если внутренняя часть цикла может быть векторизована, она выполняет шаги SIMD:
for(i=0; i<get_local_size(0); i+=SIMD) {
4) Каждый поток TBB разворачивается один раз во время выполнения OpenCL, и они повторно используются. Каждый поток TBB привязан к виртуальному ядру, т.е. во время вычисления нет миграции нитей.
Я также принимаю ответ @natchouf-s.