0

Nvidia 不允许在用 CUDA C/C++ 编写的 GPU 内核的编译流程中访问生成的 LLVM IR。如果我使用 Alea GPU,我想知道这是否可能?换句话说,Alea GPU 编译过程是否允许保留生成的优化/未优化 LLVM IR 代码?

4

1 回答 1

3

是的,你是对的,Nvidia 没有向你显示 LLVM IR,你只能获取 PTX 代码。虽然 Alea GPU 允许您以多种方式访问​​ LLVM IR:

方法一

您使用基于工作流的方法将 GPU 模块编码为模板,然后将模板编译为 LLVM IR 模块,然后将 LLVM IRModule(可选地与其他一些 IR 模块)链接到 PTX 模块中。最后,将 PTX 模块加载到 GPU worker 中。当您获得 LLVM IRModule 时,您可以调用它的方法Dump()将 IR 代码打印到控制台。或者您可以将位码作为byte[].

我建议您在此处阅读更多详细信息:

  1. 基于工作流的 GPU 编码
  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(...)

方法二

如果您使用基于方法或基于实例的方式对 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 代码扩展 GPU 功能

最后,还有一种未公开的方式,让您直接操作 LLVM IR 代码来构造函数。它是通过实现一些 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"
于 2015-07-02T14:13:24.670 回答