1

I am trying to use cuModuleLoad() in JCuda to load a vectorAdd.ptx file from /src/main/resources. The code is as follows:

cuModuleLoad(module, getClass.getResource("vectorAdd.ptx").getPath())

But the cuModuleLoad() doesn't pick up this file. It only works when I pass in the absolute path of the ptx file. But I would like to have the ptx file shipped with compile jar files. Is there any way to accomplish this?

4

1 回答 1

4

cuModuleLoadJCuda中的函数直接映射到cuModuleLoadCUDA中的相应函数。它需要一个文件名作为第二个参数。

问题是:cuModuleLoad无法加载 PTX 文件,因为 CUDA 根本不存在 PTX 文件!PTX 文件隐藏在 JAR 文件中。


当您使用 . 从 JAR 文件中获取资源时someClass.getResource(),它将指向 JAR 文件中的资源。当你做类似的事情时

System.out.println(getClass().getResource("vectorAdd.ptx").getPath());

并运行它(作为 JAR 文件),然后您将看到如下输出:

file:/U:/YourWorkspace/YourJarFile.jar!/vectorAdd.ptx

请注意.jar!部分:此路径不是真实文件的路径,而只是JAR 中资源的路径。


为了从 JAR 加载 PTX 文件,您必须将 PTX 文件从 JAR 读取到byte[]Java 端的数组中,然后将其传递给cuModuleLoadDataJCuda 的函数(对应于cuModuleLoadDataCUDA 的函数)。

这是一个将 PTX 数据从 JAR 文件加载到字节数组中的示例,表示可以传递给的以零结尾的字符串cuModuleLoadData

import static jcuda.driver.JCudaDriver.cuCtxCreate;
import static jcuda.driver.JCudaDriver.cuDeviceGet;
import static jcuda.driver.JCudaDriver.cuInit;
import static jcuda.driver.JCudaDriver.cuModuleGetFunction;
import static jcuda.driver.JCudaDriver.cuModuleLoadData;
import static jcuda.runtime.JCuda.cudaDeviceReset;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;

import jcuda.driver.CUcontext;
import jcuda.driver.CUdevice;
import jcuda.driver.CUfunction;
import jcuda.driver.CUmodule;
import jcuda.driver.JCudaDriver;

public class JCudaPtxInJar
{
    public static void main(String args[]) throws IOException
    {
        // Initialization
        JCudaDriver.setExceptionsEnabled(true);
        cuInit(0);
        CUdevice device = new CUdevice();
        cuDeviceGet(device, 0);
        CUcontext context = new CUcontext();
        cuCtxCreate(context, 0, device);

        // Read the PTX data into a zero-terminated string byte array
        byte ptxData[] = toZeroTerminatedStringByteArray(
            JCudaPtxInJar.class.getResourceAsStream(
                "JCudaVectorAddKernel.ptx"));

        // Load the module data
        CUmodule module = new CUmodule();
        cuModuleLoadData(module, ptxData);

        // Obtain a function pointer to the "add" function
        // and print a simple test/debug message
        CUfunction function = new CUfunction();
        cuModuleGetFunction(function, module, "add");
        System.out.println("Got function "+function);

        cudaDeviceReset();
    }

    /**
     * Read the contents of the given input stream, and return it
     * as a byte array containing the ZERO-TERMINATED string data 
     * from the stream. The caller is responsible for closing the
     * given stream.
     * 
     * @param inputStream The input stream
     * @return The ZERO-TERMINATED string byte array
     * @throws IOException If an IO error occurs
     */
    private static byte[] toZeroTerminatedStringByteArray(
        InputStream inputStream) throws IOException
    {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        byte buffer[] = new byte[8192];
        while (true)
        {
            int read = inputStream.read(buffer);
            if (read == -1)
            {
                break;
            }
            baos.write(buffer, 0, read);
        }
        baos.write(0);
        return baos.toByteArray();
    }
}

编译它并将其打包到 JAR 中(/resources/JCudaVectorAddKernel.ptx当然还有 PTX 文件)将允许您启动程序并从 JAR 中的 PTX 中获取示例函数。

于 2015-12-15T17:56:11.083 回答