Я работаю над JIT, который использует LLVM. Язык имеет небольшую среду выполнения, написанную на C ++, которую я компилирую в LLVM IR, используя clang
clang++ runtime.cu --cuda-gpu-arch=sm_50 -c -emit-llvm
а затем загрузите файлы * .bc, сгенерируйте дополнительный IR и выполните на лету. Причина использования CUDA заключается в том, что я хочу добавить некоторое ускорение GPU во время выполнения. Тем не менее, это вводит специфические внешние функции CUDA, которые дают такие ошибки, как:
LLVM ERROR: Program used external function 'cudaSetupArgument' which could not be resolved!
Как обсуждалось Вот, Обычно это решается путем включения соответствующих библиотек при компиляции программы:
g++ main.c cmal.o -L/usr/local/cuda/lib64 -lcudart
Однако я не уверен, как включать библиотеки в модули JITed, используя LLVM. я нашел этот Вопрос, который предполагал, что раньше было возможно добавить библиотеки в модули в JIT следующим образом:
[your module]->addLibrary("m");
К сожалению, это устарело. Кто-нибудь может сказать мне лучший способ сделать это сейчас? Дайте мне знать, если мне нужно предоставить больше информации!
Кроме того, я не совсем уверен, является ли это лучшим способом включить разгрузку графического процессора в мой JIT, поэтому, если кто-то может указать мне лучший метод, тогда сделайте 🙂
Спасибо!
РЕДАКТИРОВАТЬ: я использую LLVM 5.0 и движок JIT я использую от llvm/ExecutionEngine/ExecutionEngine.h
точнее я создаю это так:
EngineBuilder EB(std::move(module));
ExecutionEngine *EE = EB.create(targetMachine);
Вам нужно подробно рассказать вашему движку JIT о других символах.
Если они находятся в динамической библиотеке (dylib
, so
, dll
) тогда можно просто позвонить
sys::DynamicLibrary::LoadLibraryPermanently("path_to_some.dylib")
с путем к динамической библиотеке.
Если символы находятся в объектном файле или архиве, то это требует немного больше работы: вам нужно будет загрузить их в память и добавить в ExecutionEngine
используя свои API.
Вот пример для объектного файла:
std::string objectFileName("some_object_file.o");
ErrorOr<std::unique_ptr<MemoryBuffer>> buffer =
MemoryBuffer::getFile(objectFileName.c_str());
if (!buffer) {
// handle error
}
Expected<std::unique_ptr<ObjectFile>> objectOrError =
ObjectFile::createObjectFile(buffer.get()->getMemBufferRef());
if (!objectOrError) {
// handle error
}
std::unique_ptr<ObjectFile> objectFile(std::move(objectOrError.get()));
auto owningObject = OwningBinary<ObjectFile>(std::move(objectFile),
std::move(buffer.get()));
executionEngine.addObjectFile(std::move(owningObject));
Для архивов заменить типы шаблонов ObjectFile
с Archive
и позвоните
executionEngine.addArchive(std::move(owningArchive));
в конце.
Других решений пока нет …