Лекция 9. Драйвер компиляции (1265190)
Текст из файла
Лихогруд Николай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.
Характеристики
Тип файла PDF
PDF-формат наиболее широко используется для просмотра любого типа файлов на любом устройстве. В него можно сохранить документ, таблицы, презентацию, текст, чертежи, вычисления, графики и всё остальное, что можно показать на экране любого устройства. Именно его лучше всего использовать для печати.
Например, если Вам нужно распечатать чертёж из автокада, Вы сохраните чертёж на флешку, но будет ли автокад в пункте печати? А если будет, то нужная версия с нужными библиотеками? Именно для этого и нужен формат PDF - в нём точно будет показано верно вне зависимости от того, в какой программе создали PDF-файл и есть ли нужная программа для его просмотра.