Как вы профилируете и оптимизируете ядра CUDA?
Я немного знаком с визуальным профилировщиком CUDA и таблицей занятости, хотя я, вероятно, не использую их так хорошо, как мог. Профилирование и оптимизация кода CUDA не похоже на профилирование и оптимизацию кода, который выполняется на процессоре. Поэтому я надеюсь извлечь уроки из вашего опыта о том, как извлечь максимальную пользу из моего кода.
Недавно был найден быстрый код для определения номеров самообслуживания, и я предоставил CUDA. Я не удовлетворен тем, что этот код работает так быстро, как может быть, но я в недоумении, чтобы выяснить, как правильно и на каком инструменте я могу получить ответы.
Как вы определяете способы ускорения работы ваших ядер CUDA?
Ответы
Ответ 1
Если вы разрабатываете Linux, CUDA Visual Profiler предоставляет вам массу информации, зная, что с ней делать, может быть немного сложно. В Windows вы также можете использовать CUDA Visual Profiler или (в Vista/7/2008), вы можете использовать Nexus, который прекрасно сочетается с Visual Studio и дает вам общую информацию о профиле хоста и GPU.
Как только вы получите данные, вам нужно знать, как их интерпретировать. Продвинутая версия CUDA C от GTC содержит несколько полезных советов. Главное, на что нужно обратить внимание:
- Оптимальный доступ к памяти: вам нужно знать, чего вы ожидаете от своего кода, а затем искать исключения. Поэтому, если вы всегда загружаете поплавки, и каждый поток загружает другой массив из массива, тогда вы ожидаете увидеть только 64-байтовые нагрузки (по текущему h/w). Любые другие нагрузки неэффективны. Информация о профилировании, вероятно, улучшится в будущем h/w.
- Сведение к минимуму сериализации: счетчик последовательностей "warp serialize" указывает на то, что у вас есть конфликты банка общей памяти или постоянная сериализация, презентация более подробно и что делать, как и SDK (например, пример сокращения)
- Перекрытие ввода/вывода и вычисление: здесь Nexus действительно сияет (вы можете получить ту же информацию вручную, используя cudaEvents), если у вас есть большая передача данных, которую вы хотите наложить на вычисление и ввод/вывод
- Конфигурация выполнения: калькулятор занятости может помочь в этом, но простые методы, такие как комментирование вычисления для измерения ожидаемой и измеренной полосы пропускания, действительно полезны (и наоборот для вычисления пропускной способности).
Это только начало, ознакомьтесь с презентацией GTC и другими веб-семинарами на веб-сайте NVIDIA.
Ответ 2
Профилировщик CUDA довольно груб и не предоставляет много полезной информации. Единственный способ серьезно оптимизировать ваш код (при условии, что вы уже выбрали наилучший возможный алгоритм) - это глубокое понимание архитектуры графического процессора, особенно в отношении использования разделяемой памяти, шаблонов доступа к внешней памяти, использования регистров, использования потоков, деформации и т.д.
Может быть, вы можете опубликовать свой код ядра здесь и получить обратную связь?
Форум форум разработчика nVidia CUDA также является хорошим местом для помощи в решении этой проблемы.
Ответ 3
Если вы используете Windows... Check Nexus:
http://developer.nvidia.com/object/nexus.html
Ответ 4
Я откинулся назад, потому что я не эксперт CUDA, а другие ответы довольно хорошие, если код уже довольно близок к оптимальному. По моему опыту, это большой ИФ, и нет никакого вреда в его проверке.
Чтобы убедиться в этом, вам нужно выяснить, действительно ли код не делает ничего, что ему действительно не нужно делать. Вот как я могу убедиться, что:
-
Запустите тот же код на ванильном процессоре и либо возьмите stackshots, либо используйте профайлер, такой как Oprofile или RotateRight/Zoom, который может дать вам эквивалентная информация.
-
Запуск его на процессоре CUDA и выполнение того же самого действия, если это возможно.
То, что вы ищете, - это строки кода, которые имеют высокий уровень занятости в стеке вызовов, как показано с помощью доли выборок стека, содержащих их. Это ваши "узкие места". Для их поиска требуется не очень большое количество образцов.