예제 #1
0
  static {
    {
      OpenCLProbeLibrary probe = new OpenCLProbeLibrary();
      try {
        if (!probe.isValid()) {
          String alt;
          if (Platform.is64Bits() && BridJ.getNativeLibraryFile(alt = "atiocl64") != null
              || BridJ.getNativeLibraryFile(alt = "atiocl32") != null
              || BridJ.getNativeLibraryFile(alt = "atiocl") != null) {
            log(
                Level.INFO,
                "Hacking around ATI's weird driver bugs (using atiocl library instead of OpenCL)",
                null);
            BridJ.setNativeLibraryActualName("OpenCL", alt);
          }
        }
      } finally {
        probe = null;
        BridJ.unregister(OpenCLProbeLibrary.class);
      }
    }

    if (debug) {
      String debugArgs = System.getenv(JAVACL_DEBUG_COMPILER_FLAGS_PROP);
      if (debugArgs != null) DEBUG_COMPILER_FLAGS = Arrays.asList(debugArgs.split(" "));
      else if (Platform.isMacOSX()) DEBUG_COMPILER_FLAGS = Arrays.asList("-g");
      else DEBUG_COMPILER_FLAGS = Arrays.asList("-O0", "-g");

      int pid = ProcessUtils.getCurrentProcessId();
      log(
          Level.INFO,
          "Debug mode enabled with compiler flags \""
              + StringUtils.implode(DEBUG_COMPILER_FLAGS, " ")
              + "\" (can be overridden with env. var. JAVACL_DEBUG_COMPILER_FLAGS_PROP)");
      log(
          Level.INFO,
          "You can debug your kernels with GDB using one of the following commands :\n"
              + "\tsudo gdb --tui --pid="
              + pid
              + "\n"
              + "\tsudo ddd --debugger \"gdb --pid="
              + pid
              + "\"\n"
              + "More info here :\n"
              + "\thttp://code.google.com/p/javacl/wiki/DebuggingKernels");
    }
    CL = new OpenCLLibrary();
  }
예제 #2
0
/**
 * Entry point class for the OpenCL4Java Object-oriented wrappers around the OpenCL API.<br>
 *
 * @author Olivier Chafik
 */
public class JavaCL {

  static final boolean debug =
      "true".equals(System.getProperty("javacl.debug"))
          || "1".equals(System.getenv("JAVACL_DEBUG"));
  static final boolean verbose =
      debug
          || "true".equals(System.getProperty("javacl.verbose"))
          || "1".equals(System.getenv("JAVACL_VERBOSE"));
  static final int minLogLevel = Level.WARNING.intValue();

  static final String JAVACL_DEBUG_COMPILER_FLAGS_PROP = "JAVACL_DEBUG_COMPILER_FLAGS";
  static List<String> DEBUG_COMPILER_FLAGS;

  static boolean shouldLog(Level level) {
    return verbose || level.intValue() >= minLogLevel;
  }

  static boolean log(Level level, String message, Throwable ex) {
    if (!shouldLog(level)) return true;
    Logger.getLogger(JavaCL.class.getSimpleName()).log(level, message, ex);
    return true;
  }

  static boolean log(Level level, String message) {
    log(level, message, null);
    return true;
  }

  private static int getPlatformIDs(
      int count, Pointer<cl_platform_id> out, Pointer<Integer> pCount) {
    try {
      return CL.clIcdGetPlatformIDsKHR(count, out, pCount);
    } catch (Throwable th) {
      return CL.clGetPlatformIDs(count, out, pCount);
    }
  }

  @org.bridj.ann.Library("OpenCLProbe")
  @org.bridj.ann.Convention(org.bridj.ann.Convention.Style.StdCall)
  public static class OpenCLProbeLibrary {
    static {
      BridJ.setNativeLibraryActualName("OpenCLProbe", "OpenCL");
      BridJ.register();
    }

    @org.bridj.ann.Optional
    public static synchronized native int clGetPlatformIDs(
        int cl_uint1,
        Pointer<OpenCLLibrary.cl_platform_id> cl_platform_idPtr1,
        Pointer<Integer> cl_uintPtr1);

    @org.bridj.ann.Optional
    public static synchronized native int clIcdGetPlatformIDsKHR(
        int cl_uint1,
        Pointer<OpenCLLibrary.cl_platform_id> cl_platform_idPtr1,
        Pointer<Integer> cl_uintPtr1);

    public boolean isValid() {
      Pointer<Integer> pCount = allocateInt();
      int err;
      try {
        err = clIcdGetPlatformIDsKHR(0, null, pCount);
      } catch (Throwable th) {
        try {
          err = clGetPlatformIDs(0, null, pCount);
        } catch (Throwable th2) {
          return false;
        }
      }
      return err == OpenCLLibrary.CL_SUCCESS && pCount.get() > 0;
    }
  }

  static final OpenCLLibrary CL;

  static {
    {
      OpenCLProbeLibrary probe = new OpenCLProbeLibrary();
      try {
        if (!probe.isValid()) {
          String alt;
          if (Platform.is64Bits() && BridJ.getNativeLibraryFile(alt = "atiocl64") != null
              || BridJ.getNativeLibraryFile(alt = "atiocl32") != null
              || BridJ.getNativeLibraryFile(alt = "atiocl") != null) {
            log(
                Level.INFO,
                "Hacking around ATI's weird driver bugs (using atiocl library instead of OpenCL)",
                null);
            BridJ.setNativeLibraryActualName("OpenCL", alt);
          }
        }
      } finally {
        probe = null;
        BridJ.unregister(OpenCLProbeLibrary.class);
      }
    }

    if (debug) {
      String debugArgs = System.getenv(JAVACL_DEBUG_COMPILER_FLAGS_PROP);
      if (debugArgs != null) DEBUG_COMPILER_FLAGS = Arrays.asList(debugArgs.split(" "));
      else if (Platform.isMacOSX()) DEBUG_COMPILER_FLAGS = Arrays.asList("-g");
      else DEBUG_COMPILER_FLAGS = Arrays.asList("-O0", "-g");

      int pid = ProcessUtils.getCurrentProcessId();
      log(
          Level.INFO,
          "Debug mode enabled with compiler flags \""
              + StringUtils.implode(DEBUG_COMPILER_FLAGS, " ")
              + "\" (can be overridden with env. var. JAVACL_DEBUG_COMPILER_FLAGS_PROP)");
      log(
          Level.INFO,
          "You can debug your kernels with GDB using one of the following commands :\n"
              + "\tsudo gdb --tui --pid="
              + pid
              + "\n"
              + "\tsudo ddd --debugger \"gdb --pid="
              + pid
              + "\"\n"
              + "More info here :\n"
              + "\thttp://code.google.com/p/javacl/wiki/DebuggingKernels");
    }
    CL = new OpenCLLibrary();
  }

  /** List the OpenCL implementations that contain at least one GPU device. */
  public static CLPlatform[] listGPUPoweredPlatforms() {
    CLPlatform[] platforms = listPlatforms();
    List<CLPlatform> out = new ArrayList<CLPlatform>(platforms.length);
    for (CLPlatform platform : platforms) {
      if (platform.listGPUDevices(true).length > 0) out.add(platform);
    }
    return out.toArray(new CLPlatform[out.size()]);
  }
  /** Lists all available OpenCL implementations. */
  public static CLPlatform[] listPlatforms() {
    Pointer<Integer> pCount = allocateInt();
    error(getPlatformIDs(0, null, pCount));

    int nPlats = pCount.get();
    if (nPlats == 0) return new CLPlatform[0];

    Pointer<cl_platform_id> ids = allocateTypedPointers(cl_platform_id.class, nPlats);

    error(getPlatformIDs(nPlats, ids, null));
    CLPlatform[] platforms = new CLPlatform[nPlats];

    for (int i = 0; i < nPlats; i++) {
      platforms[i] = new CLPlatform(ids.get(i));
    }
    return platforms;
  }

  /**
   * Creates an OpenCL context formed of the provided devices.<br>
   * It is generally not a good idea to create a context with more than one device, because much
   * data is shared between all the devices in the same context.
   *
   * @param devices devices that are to form the new context
   * @return new OpenCL context
   */
  public static CLContext createContext(
      Map<CLPlatform.ContextProperties, Object> contextProperties, CLDevice... devices) {
    return devices[0].getPlatform().createContext(contextProperties, devices);
  }

  /**
   * Allows the implementation to release the resources allocated by the OpenCL compiler. <br>
   * This is a hint from the application and does not guarantee that the compiler will not be used
   * in the future or that the compiler will actually be unloaded by the implementation. <br>
   * Calls to Program.build() after unloadCompiler() will reload the compiler, if necessary, to
   * build the appropriate program executable.
   */
  public static void unloadCompiler() {
    error(CL.clUnloadCompiler());
  }

  /**
   * Returns the "best" OpenCL device (currently, the one that has the largest amount of compute
   * units).<br>
   * For more control on what is to be considered a better device, please use the {@link
   * JavaCL#getBestDevice(CLPlatform.DeviceFeature[]) } variant.<br>
   * This is currently equivalent to <code>getBestDevice(MaxComputeUnits)</code>
   */
  public static CLDevice getBestDevice() {
    return getBestDevice(CLPlatform.DeviceFeature.MaxComputeUnits);
  }
  /**
   * Returns the "best" OpenCL device based on the comparison of the provided prioritized device
   * feature.<br>
   * The returned device does not necessarily exhibit the features listed in preferredFeatures, but
   * it has the best ordered composition of them.<br>
   * For instance on a system with a GPU and a CPU device, <code>
   * JavaCL.getBestDevice(CPU, MaxComputeUnits)</code> will return the CPU device, but on another
   * system with two GPUs and no CPU device it will return the GPU that has the most compute units.
   */
  public static CLDevice getBestDevice(CLPlatform.DeviceFeature... preferredFeatures) {
    List<CLDevice> devices = new ArrayList<CLDevice>();
    for (CLPlatform platform : listPlatforms())
      devices.addAll(Arrays.asList(platform.listAllDevices(true)));
    return CLPlatform.getBestDevice(Arrays.asList(preferredFeatures), devices);
  }
  /** Creates an OpenCL context with the "best" device (see {@link JavaCL#getBestDevice() }) */
  public static CLContext createBestContext() {
    return createBestContext(DeviceFeature.MaxComputeUnits);
  }

  /**
   * Creates an OpenCL context with the "best" device based on the comparison of the provided
   * prioritized device feature (see {@link JavaCL#getBestDevice(CLPlatform.DeviceFeature...) })
   */
  public static CLContext createBestContext(CLPlatform.DeviceFeature... preferredFeatures) {
    CLDevice device = getBestDevice(preferredFeatures);
    return device.getPlatform().createContext(null, device);
  }

  /**
   * Creates an OpenCL context able to share entities with the current OpenGL context.
   *
   * @throws RuntimeException if JavaCL is unable to create an OpenGL-shared OpenCL context.
   */
  public static CLContext createContextFromCurrentGL() {
    RuntimeException first = null;
    for (CLPlatform platform : listPlatforms()) {
      try {
        CLContext ctx = platform.createContextFromCurrentGL();
        if (ctx != null) return ctx;
      } catch (RuntimeException ex) {
        if (first == null) first = ex;
      }
    }
    throw new RuntimeException(
        "Failed to create an OpenCL context based on the current OpenGL context", first);
  }

  static File userJavaCLDir = new File(new File(System.getProperty("user.home")), ".javacl");
  static File userCacheDir = new File(userJavaCLDir, "cache");

  static synchronized File createTempFile(String prefix, String suffix, String category) {
    File dir = new File(userJavaCLDir, category);
    dir.mkdirs();
    try {
      return File.createTempFile(prefix, suffix, dir);
    } catch (IOException ex) {
      throw new RuntimeException(
          "Failed to create a temporary directory for category '"
              + category
              + "' in "
              + userJavaCLDir
              + ": "
              + ex.getMessage(),
          ex);
    }
  }

  static synchronized File createTempDirectory(String prefix, String suffix, String category) {
    File file = createTempFile(prefix, suffix, category);
    file.delete();
    file.mkdir();
    return file;
  }
}