Лекция 9. Драйвер компиляции (Лекции)
Описание файла
Файл "Лекция 9. Драйвер компиляции" внутри архива находится в папке "Лекции". PDF-файл из архива "Лекции", который расположен в категории "". Всё это находится в предмете "технология cuda на кластерах с gpu" из 12 семестр (4 семестр магистратуры), которые можно найти в файловом архиве МГУ им. Ломоносова. Не смотря на прямую связь этого архива с МГУ им. Ломоносова, его также можно найти и в других разделах. .
Просмотр PDF-файла онлайн
Текст из PDF
Лихогруд Николайn.lihogrud@gmail.comЧасть девятаяДрайвер компиляции NVCC, цепочка компиляцииДрайвер? nvcc – не компилятор, а т.н. «драйвер компиляции» Реализует цепочку компиляции путем вызовавспомогательных программ и компиляторов для полученияобъектных модулей и линковки исполняемого файла -c, -o, -g, -L, -l, -I, -E Парсятся и прокидываются хост-компилятору C/C++NVCC: вспомогательные программы gcc (Linux) , cl (Windows)– компилятор хост-кода Препроцессинг – разворачивание макросов и инклюдов Компиляция объектных файлов host-кода совстроенным device-ассемблером Линковка исполняемых файлов Можно указать любой совместимый через опцию -ccbinNVCC: вспомогательные программы cudafe – CUDA front-end разделяет *.cu файл на C/C++ код CPU и код для GPU cudafe не запускается для файлов с другим расширением CUDA-расширения С++ (атрибуты, встроенные функции ипеременные) можно использовать только в*.cu сicc – CUDA-компилятор на базе LLVM для с++ device-кода Компилирует код для GPU, экстрагированный cudafe, впромежуточный код PTX Раньше использовался nvopencc на базе open64NVCC: вспомогательные программы ptxas – PTX assembler, компилятор для промежуточногокода PTX Компилирует PTX в бинарный код (ассемблер) подзаданные архитектуры Результат сохраняет в *.cubin (CUDA binary) fatbinary: Объединяет бинарные образы для различныхархитектурсхема NVCCИзучаем работу NVCC -v : вывести цепочку компиляции -keep : не удалять промежуточные файлы, создаваемыево время выполнения цепочки -v -keep : вывести цепочку компиляции и не удалятьпромежуточные файлы Можно полностью проследить весь процесс -clean : удалить промежуточные файлы, созданные припомощи опции -keepnvcc -keepnvcc -v -keepПрепроцессинг обычным компилятором $ gcc -D__CUDA_ARCH__=200 -E -x c++DCUDA_DOUBLE_MATH_FUNCTIONSI/opt/cuda/bin/../include""sum.cpp1.ii" "sum.cu"-D__CUDACC__ -D__NVCC__ "-include "cuda_runtime.h" -m64 -oРазделение на Device и Host код $ cudafe -w --m64 --gnu_version=40603 --c--gen_c_file_name"sum.cudafe2.c" --stub_file_name "sum.cudafe2.stub.c" -gen_device_file_name "sum.cudafe2.gpu" --nv_arch "compute_20" -module_id_file_name "sum.module_id" --include_file_name"sum.fatbin.c" "sum.cpp2.i"nvcc -v -keepГенерация промежуточного представления $ cicc-arch compute_20 -m64 -ftz=0 -prec_div=1 -prec_sqrt=1 -fmad=1"sum" "sum.cpp3.i" -o "sum.ptx"Компиляция бинарного кода $ ptxas-arch=sm_20 -m64"sum.ptx"-o "sum.sm_20.cubin"Объединение .cubin и .ptx в fatbin $ fatbinary --create="sum.fatbin" -64 --key="192010da74fff017" --ident="sum.cu" "--image=profile=sm_20,file=sum.sm_20.cubin" "-image=profile=compute_20,file=sum.ptx" --embeddedfatbin="sum.fatbin.c" --cudanvcc -v -keepВставить fatbin в хост-код $ gcc -D__CUDA_ARCH__=200 -E -x c++DCUDA_DOUBLE_MATH_FUNCTIONSI/opt/cuda/bin/../include""sum.cudafe1.cpp"-D__CUDA_PREC_DIV -D__CUDA_PREC_SQRT "-m64 -o "sum.cu.cpp.ii"Компиляция хост кода в объектный файл $ gcc -c -x c++ "-I/opt/cuda/bin/../include"-fpreprocessed -m64 -o"sum.o" "sum.cu.cpp.ii"Линковка $ g++ -m64 -o "a.out" -Wl,--start-group "sum.o"L/opt/cuda/bin/../lib64" -lcudart -Wl,--end-group"-Управление компиляцией NVCC -Xcompiler, -Xlinker, -Xptxas передать одну опцию компиляции на соответствующийшаг цепочки -gpu, -ptx, -cubin, -fatbin, -cuda Остановить выполнение цепочки на соответствующемшаге При помощи -o можно указать в какой файл сохранитьрезультаты последнего шагаБинарная совместимость Различные поколения CUDA-устройств имеют различныеаппаратные возможности Поддерживать совместимость архитектур не эффективно Nvidia поддерживает прямую бинарную совместимостьтолько в рамках одного поколения Бинарный код для Compute Capability x.y будетработать только на устройствах с Compute Capabilityx.z, где z >= y Обратной бинарной совместимости нетЗачем нужен ptx? На этапе компиляции в общем случае не известнаархитектура, на которой будет производится запуск Чтобы исполняемые файлы работали на будущихархитектурах была введена двухшаговая схемакомпиляцииГенерация псевдо-ассеблера для виртуальной архитектуры2.
Компиляция полученного ассемблера для конкретнойфизической архитектуры1.PTX– “Parallel Thread Execution” Псевдо-ассемблер для «виртуальной архитектуры» Генерируется компилятором cicc из C++ кода для GPU,экстрагированного фронтендом Доступен в текстовом формате, может быть получен поключу nvcc -ptx или nvcc -keep PTX для некоторой виртуальной архитектуры может бытьскомпилирован для любой физической архитектуры с темже или большим СССтатическая и JIT компиляция• В параметрах nvcc можно задать нескольковиртуальных/физических архитектур, для которыхтребуется встроить PTX/бинарный код• Во время выполнения программы производится поискбинарного кода для архитектуры устройства, на которомбудет производится запуск• Если подходящего кода нет – JIT компилируется PTX дляближайшей виртуальнойФлаги NVCC$nvcc -gencode arch=compute_20,code=sm_20Для какой виртуальнойархитектуры сгенерироватьptxДля какой архитектуры встроить код••Для виртуальной встроится ptxДля физической встроитсябинарный кодВиртуальные - compute_11, compute_12, compute_13,compute_20, compute_30, compute_32, compute_35,compute_50, compute_52Физические - sm_11, sm_12, sm_13, sm_20, sm_21, sm_30,sm_32, sm_35, sm_50, sm_52Флаги NVCC$nvcc -arch=compute_20-code=compute_20,sm_20,sm_35Эквиваленто$nvcc –gencode arch=compute_20,code=sm_20 \–gencode arch=compute_20,code=sm_20 \–gencode arch=compute_20,code=compute_20$nvcc -arch=sm_20Эквиваленто$nvcc –arch=compute_20 -code=compute_20,sm_20Статическая компиляция$nvcc -arch=compute_20 –code=sm_20JIT компиляция$nvcc -arch=compute_20Когда происходит JIT-компиляция При создании контекста устройства в его память загружаетсябинарный код для всех ядер программы Вне зависимости от того будут ли эти ядра на этом устройствезапускаться Если для какого-либо ядра отсутствует бинарный код – JIT-компилируется PTX для ближайшей виртуальной архитектуры Если PTX нет, то при последующем запуске ядра произойдетошибкаПроблемы с JIT-компиляцией Контекст устройства создается при первом вызове функции, несвязанной с выбором устройства/проверкой версии CUDA cudaMalloc, запуск ядра Можно отследить через $set cuda context_events on вcuda-gdb JIT-компиляция ядер может исказить время работы команды,вызвавшей создание контекстаПроблемы с JIT-компиляцией Если в программе много ядер (например, подключена CUDA-библиотека), может получиться значительная задержка Отсутствующий бинарный код компилируется под всеархитектуры используемых устройств в программе с multi-GPU Несколько задержек в одном запускеCompute Cache Драйвер автоматически кеширует JIT-скомпилированныйбинарный код в т.н.
«Compute Cache» При последующих запусках программы готовыйбинарный код ядер будет браться из негоУправление JIT компиляцией и кешемПеременные окружения: CUDA_CACHE_DISABLE - 0 или 1, по умолчанию 0Когда равно 1 кеш не используется. CUDA_CACHE_PATH – путь до папки с кешем. По умолчанию: На Windows:%APPDATA%\NVIDIA\ComputeCache На MacOS:~/Library/Application\ Support/NVIDIA/ComputeCache На Linux~/.nv/ComputeCacheУправление JIT компиляцией и кешемПеременные окружения: CUDA_CACHE_MAXSIZE – максимальный размер кеша. Поумолчанию, 33554432 (32 MB)Когда лимит превышается из кеша удаляются старые ядра CUDA_FORCE_PTX_JIT - 0 или 1, по умолчанию 0.Когда равно 1 игнорируется бинарный код, встроенный впрограмму/сохраненный в кеше.Рекомендации По возможности избегайте JIT-компиляции ядер, т.к.
это даетнепредсказуемую задержку при выполнении первой команды,вызывающей создание контекста Указывайте как можно больше физических архитектур прикомпиляцииУвеличивается время компиляции и размерисполняемого файла Задавайте максимальный размер кеша достаточным длявмещения всех ядер программы, если JIT-компиляциянеизбежнаCUBIN - CUDA binary Формат исполняемого/линкуемого файла для GPU,основанный на ELF••Содержит секции, используемые для создания образавыполняемой программы/линковки:••••https://ru.wikipedia.org/wiki/Executable_and_Linkable_Format.symtab – таблица символов.text.* - ассемблер ядер.nv_debug_*, .debug_* - отладочная информацияГенерируется для физических архитектур компиляторомptxas из ptx-кодаFATBIN – fat binaryИспользуется для объединения Различных *.cubin с бинарным кодом под физическиеархитектуры Различных *.ptx с ptx-кодом под виртуальныеархитектурыГененируется утилитой fatbinary для заданного наборафайлов-образовКомпиляция нескольких архитектур$nvcc -arch=compute_20$$$$-code=compute_20,sm_20,sm_35cicc -arch compute_20 … -o "main.ptx”ptxas -arch=sm_35 -m64 "main.ptx" -o "main.sm_35.cubin"ptxas -arch=sm_20 -m64 "main.ptx" -o "main.sm_20.cubin"fatbinary --create="main.fatbin" … \"--image=profile=sm_35,file=main.sm_35.cubin" \"--image=profile=sm_20,file=main.sm_20.cubin" \"--image=profile=compute_20,file=main.ptx" \--embedded-fatbin="main.fatbin.c" --cudaВстраивание fatbin в хост-кодВместе с *.fatbin генерируется *.fatbin.c$fatbinary --create="main.fatbin" -64 -key="46fb71d1e611b812" --ident="main.cu" \"--image=profile=compute_20,file=main.ptx" \"--image=profile=sm_21,file=main.sm_21.cubin" \"--image=profile=sm_20,file=main.sm_20.cubin" \--embedded-fatbin="main.fatbin.c" --cuda*fatbin.cИнициализация elf-символа fatbinData вasm(секции .nv_fatbin байтами *.fatbin".section .nv_fatbin, \"a\"\n“".align 8\n“"fatbinData:\n“".quad 0x00100001ba55ed50,0x00000000000011d8,0x0000004801010002,0x0000000000000828\n“".quad 0x0000000000000000,0x0000002300010007,0x0000000700000040,0x0000000000000015\n“".quad 0x0000000000000000,0x0000000000000000,0x0075632e6e69616d,0x33010102464c457f\n“...".quad 0x0000000000000a0a\n“".text");extern const unsigned long long fatbinData[573];Символ, в котором лежит*.fatbin в объектном файлеstatic const __fatBinC_Wrapper_t __fatDeviceText \__attribute__ ((aligned (8))) __attribute__ ((section (“.nvFatBinSegment”))) = \{ 0x466243b1, 1, fatbinData, 0 };Задание elf-сегмента.nvFatBinSegmentВстраивание fatbin в хост-код В main.cudafe1.cpp:#include "main.cudafe1.stub.c" В main.cudafe1.stub.c:#include "main.fatbin.c" Компиляция$gcc -E -x c++ … "main.cu.cpp.ii" "main.cudafe1.cpp"$gcc -c -x c++ … -o "main.o" "main.cu.cpp.ii"cuobjdumpУтилита, схожая с Linux objdump. Выводит информацию, содержащуюся в объектныхфайлах *.cubin, *.fatbin или файлах, в которыевстроены *.fatbinОпции cuobjdump для FATBIN•$cuobjdump –lelf a.out$cuobjdump –lptx a.outВывести имена встроенных cubin/ptx образов•$cuobjdump –all main.fatbinВывести все встроенные образы•$cuobjdump –ptx main.oВывести встроенный ptx•$cuobjdump … -arch=sm_20Фильтровать вывод по архитектуреОпции cuobjdump для FATBIN/CUBIN•$cuobjdump –sass main.cubinДизасеблировать и вывести инструкции бинарного кода•$cuobjdump –elf main.сubinВывести elf-секции cubinДля fatbin вывести elf-секции всех встроенных *.cubin•$cuobjdump –symbols main.cubinВывести таблицу символов cubinДля fatbin вывести таблицы символов всехвстроенных *.cubincuobjdump пример$cuobjdump -symbols -arch=sm_35 main.oFatbin elf code:================arch = sm_35code version = [1,7]producer = cudahost = linuxcompile_size = 64bitidentifier = main.cusymbols:STT_SECTIONSTT_SECTIONSTT_OBJECTSTT_SECTIONSTT_FUNCSTB_LOCALSTB_LOCALSTB_LOCALSTB_LOCALSTB_GLOBAL.text._Z6kernelPfS_.nv.globalsomeArray.nv.constant0._Z6kernelPfS__Z6kernelPfS_cuobjdump пример$nvcc -v --keep -arch=compute_20 \-code=sm_20,sm_35,compute_20 main.cu$cuobjdump -lelf main.oELF file1: main.sm_35.cubinELF file2: main.sm_20.cubin$cuobjdump -lptx main.oPTX file1: main.sm_20.ptxПроблема раздельной компиляции До cuda 5.0 не поддерживалась раздельная компиляции CUDAкода, только «Whole program compilation» Все зависимости ядра должны располагаться в той жеединице компиляции, то и само ядро extern игнорируется Начиная с cuda 5.0 для архитектур >= sm_20 поддерживаетсяраздельная компиляция CUDA-кода, но по умолчаниюпроисходит whole program compilation Нужны дополнительные действияDevice relocalable code По умолчанию все функции инлайнятся в ядра, а их телаудаляются Остаётся только код ядер, с заинлайненными зависимостями Такой код ни с чем не слинкуешь Device relocalable code – код, в котором не удалены телафункций без атрибутов static Такой код можно линковатьСхема линковки1.