Позволяет ли Alea GPU сохранять IR-код LLVM в цепочке компиляции?

Nvidia не разрешает доступ к сгенерированному LLVM IR в потоке компиляции ядра графического процессора, написанного на CUDA C/C++. Я хотел бы знать, возможно ли это, если я использую Alea GPU? Другими словами, позволяет ли процедура компиляции Alea GPU сохранить сгенерированный оптимизированный/неоптимизированный код LLVM IR?


person Farzad    schedule 02.07.2015    source источник


Ответы (1)


Да, вы правы, Nvidia не показывает вам LLVM IR, вы можете получить только код PTX. В то время как Alea GPU позволяет получить доступ к LLVM IR несколькими способами:

Способ 1

Вы используете метод на основе рабочего процесса для кодирования модуля GPU как шаблон, затем вы компилируете шаблон в ИК-модуль LLVM, затем связываете LLVM IRModule, возможно, с некоторыми другими ИК-модулями, в модуль PTX. Наконец, вы загружаете модуль PTX в рабочий процесс GPU. Пока вы получаете LLVM IRModule, вы можете вызвать его метод Dump() для вывода кода IR на консоль. Или вы можете получить биткод как byte[].

Рекомендую прочитать подробнее здесь:

  1. Кодирование графического процессора на основе рабочего процесса
  2. рабочие процессы в деталях

F# будет примерно таким:

let template = cuda {
    // define your kernel functions or other gpu moudle stuff
    let! kernel = <@ fun .... @> |> Compiler.DefineKernel

    // return an entry pointer for this module, something like the 
    // main() function for a C program
    return Entry(fun program ->
        let worker = program.Worker
        let kernel = program.Apply kernel
        let main() = ....
        main ) }

let irModule = Compiler.Compile(template).IRModule
irModule.Dump() // dump the IR code

let ptxModule = Compiler.Link(irModule).PTXModule
ptxModule.Dump()

use program = worker.LoadProgram(ptxModule)
program.Run(...)

Способ 2

Если вы используете на основе метода или На основе экземпляра способ кодирования модуля GPU, вы можете добавить обработчик событий для кода LLVM IR генерируется, а PTX генерируется, хотя Alea.CUDA.Events. Код на F# будет выглядеть так:

let desktopFolder = Environment.GetFolderPath(Environment.SpecialFolder.Desktop)
let (@@) a b = Path.Combine(a, b)
Events.Instance.IRCode.Add(fun ircode ->
    File.WriteAllBytes(desktopFolder @@ "module.ir", ircode))
Events.Instance.PTXCode.Add(fun ptxcode ->
    File.WriteAllBytes(desktopFolder @@ "module.ptx", ptxcode))

Расширение функций графического процессора с помощью кода LLVM

Наконец, есть недокументированный способ, позволяющий вам напрямую работать с IR-кодом LLVM для построения функций. Это делается с помощью атрибута, реализующего некий интерфейс построения IR. Вот простой пример, который принимает параметр, печатает его (во время компиляции) и возвращает обратно:

[<AttributeUsage(AttributeTargets.Method, AllowMultiple = false)>]
type IdentityAttribute() =
    inherit Attribute()

    interface ICustomCallBuilder with
        member this.Build(ctx, irObject, info, irParams) =
            match irObject, irParams with
            | None, irParam :: [] ->
                // the irParam is of type IRValue, which you
                // can get the LLVM native handle, by irParam.LLVM
                // Also, you can get the type by irParam.Type, which
                // is of type IRType, again, you can get LLVMTypeRef
                // handle by irParam.Type.LLVM
                // You can optionally construct LLVM instructions here.
                printfn "irParam: %A" irParam
                Some irParam
            | _ -> None

[<Identity>]
let identity(x:'T) : 'T = failwith "this is device function, better not call it from host"
person Xiang Zhang    schedule 02.07.2015