4

この質問で、JCuda で ptx モジュールをロードする際に問題があると言いました。@talonmies のアイデアの後、彼のソリューションの JCuda バージョンを実装して、複数の ptx ファイルをロードし、それらを単一のモジュールとしてロードしました。コードの関連部分は次のとおりです。

import static jcuda.driver.JCudaDriver.cuLinkAddFile;
import static jcuda.driver.JCudaDriver.cuLinkComplete;
import static jcuda.driver.JCudaDriver.cuLinkCreate;
import static jcuda.driver.JCudaDriver.cuLinkDestroy;
import static jcuda.driver.JCudaDriver.cuModuleGetFunction;
import static jcuda.driver.JCudaDriver.cuModuleLoadData;

import jcuda.driver.CUjitInputType;
import jcuda.driver.JITOptions;
import jcuda.driver.CUlinkState;
import jcuda.driver.CUfunction;

public class JCudaTestJIT{

    private CUmodule module;
    private CUfunction functionKernel;

    public void prepareModule(){
        String ptxFileName4 = "file4.ptx";
        String ptxFileName3 = "file3.ptx";
        String ptxFileName2 = "file2.ptx";
        String ptxFileName1 = "file1.ptx";

        CUlinkState linkState = new CUlinkState();
        JITOptions jitOptions = new JITOptions();
        cuLinkCreate(jitOptions, linkState);

        cuLinkAddFile(linkState, CUjitInputType.CU_JIT_INPUT_PTX, ptxFileName4, jitOptions);
        cuLinkAddFile(linkState, CUjitInputType.CU_JIT_INPUT_PTX, ptxFileName3, jitOptions);
        cuLinkAddFile(linkState, CUjitInputType.CU_JIT_INPUT_PTX, ptxFileName2, jitOptions);
        cuLinkAddFile(linkState, CUjitInputType.CU_JIT_INPUT_PTX, ptxFileName1, jitOptions);

        long sizeOut = 32768;
        byte[] image = new byte[32768];

        Pointer cubinOut = Pointer.to(image);

        cuLinkComplete(linkState, cubinOut, (new long[]{sizeOut}));

        module = new CUmodule();

        // Load the module from the image buffer
        cuModuleLoadData(module, cubinOut.getByteBuffer(0, 32768).array());

        cuLinkDestroy(linkState);

        functionKernel = new CUfunction();
        cuModuleGetFunction(functionKernel, module, "kernel");
    }

    // Other methods 
}

CUDA_ERROR_INVALID_IMAGEしかし、メソッドの呼び出し時にエラーが発生しましたcuModuleLoadDatacuLinkCompleteデバッグ中に、メソッドを呼び出して画像配列を出力として渡しても、配列は変更されておらず、クリアされていることがわかりました。出力パラメーターを正しく渡していますか? これは、JCudaで参照によって変数を渡す方法ですか?

4

1 に答える 1

4

私は 30 分前まで Java コードを 1 行も書いたことがなく、ましてや JCUDA を使用したこともありませんでしたが、ここで示したネイティブ C++ コードのほぼ文字通りの行ごとの翻訳は完全に機能するようです。

import static jcuda.driver.JCudaDriver.*;
import java.io.*;
import jcuda.*;
import jcuda.driver.*;

public class JCudaRuntimeTest
{
    public static void main(String args[])
    {
        JCudaDriver.setExceptionsEnabled(true);

        cuInit(0);
        CUdevice device = new CUdevice();
        cuDeviceGet(device, 0);
        CUcontext context = new CUcontext();
        cuCtxCreate(context, 0, device);

        CUlinkState linkState = new CUlinkState();
        JITOptions jitOptions = new JITOptions();
        cuLinkCreate(jitOptions, linkState);

        String ptxFileName2 = "test_function.ptx";
        String ptxFileName1 = "test_kernel.ptx";

        cuLinkAddFile(linkState, CUjitInputType.CU_JIT_INPUT_PTX, ptxFileName2, jitOptions);
        cuLinkAddFile(linkState, CUjitInputType.CU_JIT_INPUT_PTX, ptxFileName1, jitOptions);

        long sz[] = new long[1];
        Pointer image = new Pointer();
        cuLinkComplete(linkState, image, sz);
        System.out.println("Pointer: " + image);
        System.out.println("CUBIN size: " + sz[0]);

        CUmodule module = new CUmodule();
        cuModuleLoadDataEx(module, image, 0, new int[0], Pointer.to(new int[0]));   
        cuLinkDestroy(linkState);

        CUfunction functionKernel = new CUfunction();
        String kernelname = "_Z6kernelPfS_S_S_";
        cuModuleGetFunction(functionKernel, module, kernelname);
        System.out.println("Function: " + functionKernel);
    }
}

次のように機能します。

> nvcc -ptx -arch=sm_21 test_function.cu
test_function.cu

> nvcc -ptx -arch=sm_21 test_kernel.cu
test_kernel.cu

> javac -cp ".;jcuda-0.7.0a.jar" JCudaRuntimeTest.java
> java -cp ".;jcuda-0.7.0a.jar" JCudaRuntimeTest
Pointer: Pointer[nativePointer=0xa5a13a8,byteOffset=0]
CUBIN size: 5924
Function: CUfunction[nativePointer=0xa588160]

cuModuleLoadDataExからの戻り値cuLinkCompleteは、リンクされた CUBIN へのシステム ポインタであり、 として返される画像のサイズであることに注意してくださいlong[]。C++ コードに従って、ポインタはモジュール データ ロードに直接渡されます。

最後のコメントとして、有用な再現ケースを作成して入手する前に JCUDA と Java の基礎を学ばせるよりも、直接ハッキングできる適切な再現ケースを投稿していただければ、はるかに単純で簡単だったでしょう。それが機能します。JCUDA のドキュメントは基本的ですが完全であり、既に提供されている実際の C++ の例に対して、これを行う方法を確認するのに数分しかかかりませんでした。

于 2015-09-12T10:17:16.977 に答える