2016-07-31 4 views
2

ОК, поэтому: я успешно интегрировал первый рабочий Halide generator в cmake build system для моего маленького image-processing project.Запуск генераторов Halide от cmake с самыми оптимальными флагами и конфигурациями компилятора

Генератор реализует алгоритм изменения размера и -изменения, основанный на примере кода из кодовой базы Halide - Halide/apps/resize/resize.cpp - Я адаптировал образец, чтобы использовать параметры генератора, и связал компиляцию и вызов генераторов с моим cmake скрипт, используя функции, определенные в HalideGenerator.cmake, так же, как проект Halide делает в своем собственном скрипте сборки.

Все это отлично работает, но до сих пор мой опыт в области знаний отсутствует в сфере нюансов генерации кода. Например, я настроил метод планирования, чтобы получить наилучшую наблюдаемую эмпирическую скорость на моем ноутбуке, но, несмотря на много длинные сеансы мастеринга и считывание кода, погружается в глубины большого числа связанных с генератором генераторов tools и scripts, у меня есть только самые поверхностные понимание процесса генерации кода.

В частности, я не знаю, как подойти к этому. Лучше ли использовать настройки по умолчанию или пытаться включить определенные параметры для моей целевой платформы, и если последнее, мне нужно иметь условный код где-нибудь или может включить резервные копии двоичных файлов?

Вот о чем я говорю: в источнике урока по учебнику Halide № 15 есть сложный сценарий, который вызывает генератор с различными параметрами. Вот отрывок из комментариев коды в скрипте:

# If you're compiling and linking multiple Halide pipelines, then the 
# multiple copies of the runtime should combine into a single copy 
# (via weak linkage). If you're compiling and linking for multiple 
# different targets (e.g. avx and non-avx), then the runtimes might be 
# different, and you can't control which copy of the runtime the 
# linker selects. 

# You can control this behavior explicitly by compiling your pipelines 
# with the no_runtime target flag. Let's generate and link several 
# different versions of the first pipeline for different x86 variants: [snip] 

... от этого трудно отделить то, что должны быть сделано, от чего должны быть сделаны, или что может быть сделаны, дискреционно. Сравнительно, не нужно решать эти проблемы при настройке проектов на C++ или Objective-C (даже более византийские примеры), поскольку компилятор и компоновщик принимают большинство этих решений для вас, и в лучшем случае нуждаются в знаке или двух.

Мой вопрос: как я могу интегрировать вывода библиотеки двоичные файлы Галогенид генератора в мой существующий проект - таким образом, что выходная мощность генератора является как можно быстрее (например, использует GPU, SSE2/3, AVX2 и т.д.) без дальнейшего ограничения переносимость (например, это не будет таинственно segfault на немного другой машине)?

В частности, каким должен быть мой процесс - как в, должен ли я сначала ориентироваться на наименьший общий знаменатель, а затем постепенно увеличивать возможности экзотических процессоров?


EDIT: Как я уже говорил в комментариях ниже, это то, что мой GenGen двоичные выходы на stdout при вызове без параметров:

Imgur

ответ

1

В случае предварительной генерации ваших бинарных файлов (AOT), похоже, что вам нужна диспетчеризация времени исполнения. Ваша программа будет изучать среду CPU/GPU при запуске и решить, какие функции (AVX, OpenCL и т. Д.) Следует использовать. Это не галид.

  • Выберите набор расширенных функций для целевого (высокопроизводительный настольный графический процессор) в качестве наилучшего варианта и набор минимальных функций, которые будут работать на каждой машине (только для SSE2).
  • Создайте DLL/dylib/so для каждого из этих наборов функций, который содержит каждую функцию голодания. Они могут быть запланированы по-разному или даже построены с совершенно разными определениями Func. Вы можете иметь оба набора в одном файле исходного кода и протестировать объект Target во время генерации, чтобы выбрать между ними.
  • При запуске программы проверьте, имеются ли ваши лучшие функции для случая, и если да, загрузите эту библиотеку и используйте ее. Если какие-либо функции отсутствуют, по умолчанию используется самая совместимая версия.

Вы можете свободно выбирать, сколько наборов функций и библиотек вы хотите поддерживать.

Альтернатива заключается в том, чтобы скомпилировать ваш код Halide при запуске программы (JIT). Я рекомендую использовать объект Target, возвращенный get_jit_target_from_environment(), который использует содержимое переменной окружения HL_JIT_TARGET или «host», если эта переменная не установлена. Целевая строка «хозяин» совпадает с get_host_target() и означает, что Halide проверит среду CPU/GPU и установит все функции, которые она находит. Затем вы можете динамически протестировать объект Target и использовать графическое или графическое планирование.

+0

Эй, спасибо за то, что вернулись ко мне с этим - это «целевые строки», которые вы упомянули о тех же строках, что и @StevenJohnson, упомянутые выше, если я могу спросить? – fish2000

+1

Да. Если вы используете модель GenGen, не вызывайте 'get_jit_target_from_environment()' или 'get_host_target()'. Внутри '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' 'необходимо просто вызвать' get_target() ', который является функцией-членом' Halide :: Generator'. Ваш 'build()' будет вызываться несколько раз с другой целью каждый раз. –

1

В последнее время AOT-компиляция теперь поддерживает генерацию настроек для нескольких функций процессора с обнаружением времени выполнения. Просто используйте GenGen с разделенным запятыми списком целей и static_library в качестве вывода, например.

GenGen -e static_library, ч целевой = x86-64-Linux-sse41-AVX, x86-64-Linux-sse41, x86-64-Linux

Это создаст файл .a, который содержит:

  • 3 версии кода, скомпилированные с специализациями для AVX + SSE4.1, SSE4.1 и набившие оскомину-x86-64
  • тонкая оболочка, которая использует halide_can_use_target_features() во время выполнения вызова выберите правый для фактической целевой машины

Для получения дополнительной информации см. Func :: compile_to_multitarget_static_library() и multitarget_generator.cpp/multitarget_aottest.cpp.

+0

Разве это не доступно только для компиляции в ночных сборках? С 27 апреля не было бинарного релиза. –

+1

Вы правы. Мы должны сделать новый двоичный выпуск с этой функцией. –

+0

Просто сделал новый двоичный выпуск. –

 Смежные вопросы

  • Нет связанных вопросов^_^