Package org.encog.engine.opencl.kernels

Source Code of org.encog.engine.opencl.kernels.EncogKernel

/*
* Encog(tm) Core v2.5 - Java Version
* http://www.heatonresearch.com/encog/
* http://code.google.com/p/encog-java/
* Copyright 2008-2010 Heaton Research, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*  
* For more information on Heaton Research copyrights, licenses
* and trademarks visit:
* http://www.heatonresearch.com/copyright
*/

package org.encog.engine.opencl.kernels;

import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;

import org.encog.engine.EncogEngineError;
import org.encog.engine.opencl.EncogCLDevice;
import org.encog.engine.util.ResourceLoader;
import org.jocl.CL;
import org.jocl.Pointer;
import org.jocl.Sizeof;
import org.jocl.cl_context;
import org.jocl.cl_kernel;
import org.jocl.cl_mem;
import org.jocl.cl_program;

/**
* Defines a basic OpenCL kernal, as used by Encog. Contains the kernal source
* code and a compiled program/kernal.
*/
public class EncogKernel {

  /**
   * The source code for the kernel.
   */
  private String cl;

  /**
   * The OpenCL context.
   */
  private final cl_context context;

  /**
   * The OpenCL program.
   */
  private cl_program program;

  /**
   * The OpenCL kernel.
   */
  private cl_kernel kernel;

  /**
   * The device this kernel will run on.
   */
  private final EncogCLDevice device;

  /**
   * The name of the source resource.
   */
  private final String sourceName;

  /**
   * The size of the local work group.
   */
  private int localWork;

  /**
   * The size of the global work group.
   */
  private int globalWork;

  /**
   * The name of the function that should be called to execute this kernel,
   * from inside the OpenCL source code.
   */
  private final String kernelName;

  /**
   * Create an Encog OpenCL kernel. The Kernel will be loaded from an embedded
   * resource.
   *
   * @param device
   *            The OpenCL device to use.
   * @param sourceName
   *            The name of the kernel, from an embedded resource.
   * @param kernelName
   *            The name of the function, in the kernel, called to start the
   *            kernel.
   */
  public EncogKernel(final EncogCLDevice device, final String sourceName,
      final String kernelName) {
    this.sourceName = sourceName;
    this.context = device.getPlatform().getContext();
    this.device = device;
    this.kernelName = kernelName;
    this.cl = ResourceLoader.loadString(sourceName);
  }

  /**
   * Compile the kernel with no preprocessor defines.
   */
  public void compile() {
    compile(new HashMap<String, String>());
  }

  /**
   * Compile the kernel with a map of preprocessor defines, a collection of
   * name-value pairs.
   *
   * @param options
   *            A map of preprocessor defines.
   */
  public void compile(final Map<String, String> options) {
    // clear out any old program

    if (this.program != null) {
      CL.clReleaseProgram(this.program);
      CL.clReleaseKernel(this.kernel);
    }

    // Create the program from the source code
    final cl_program program = CL.clCreateProgramWithSource(this.context,
        1, new String[] { this.cl }, null, null);

    if (options.size() > 0) {
      final StringBuilder builder = new StringBuilder();
      for (final Entry<String, String> obj : options.entrySet()) {
        if (builder.length() > 0) {
          builder.append(" ");
        }
        builder.append("-D ");
        builder.append(obj.getKey());
        builder.append("=");
        builder.append(obj.getValue());
      }

      CL.clBuildProgram(program, 0, null, builder.toString(), null, null);
    } else {
      CL.clBuildProgram(program, 0, null, null, null, null);
    }

    // Create the kernel
    this.kernel = CL.clCreateKernel(program, this.kernelName, null);
  }

  /**
   * Create an array buffer that is read only for floats.
   * @param array The array to base on.
   * @return The memory buffer.
   */
  public cl_mem createArrayReadOnly(final float[] array) {
    return CL.clCreateBuffer(getContext(), CL.CL_MEM_READ_ONLY
        | CL.CL_MEM_COPY_HOST_PTR, Sizeof.cl_float * array.length,
        Pointer.to(array), null);
  }

  /**
   * Create an array buffer that is read only for ints.
   * @param array The array to base on.
   * @return The memory buffer.
   */
  public cl_mem createArrayReadOnly(final int[] array) {
    return CL.clCreateBuffer(getContext(), CL.CL_MEM_READ_ONLY
        | CL.CL_MEM_COPY_HOST_PTR, Sizeof.cl_int * array.length,
        Pointer.to(array), null);
  }

  /**
   * Create an array buffer that is write only.
   * @param length The length of the buffer.
   * @return The memory buffer.
   */
  public cl_mem createFloatArrayWriteOnly(final int length) {
    return CL.clCreateBuffer(getContext(), CL.CL_MEM_READ_WRITE,
        Sizeof.cl_float * length, null, null);
  }

  /**
   * @return the cl
   */
  public String getCLSource() {
    return this.cl;
  }

  /**
   * @return The OpenCL context that this kernel belongs to.
   */
  public cl_context getContext() {
    return this.context;
  }

  /**
   * @return the device
   */
  public EncogCLDevice getDevice() {
    return this.device;
  }

  /**
   * @return The size of the global work buffer.
   */
  public int getGlobalWork() {
    return this.globalWork;
  }

  /**
   * @return The OpenCL kernel.
   */
  public cl_kernel getKernel() {
    return this.kernel;
  }

  /**
   * @return The size of the local work group.
   */
  public int getLocalWork() {
    return this.localWork;
  }

  /**
   * @return Suggested max workgroup size. You will very likely crash the GPU
   *         if you go above this.
   */
  public int getMaxWorkGroupSize() {
    return (int) getWorkGroupLong(CL.CL_KERNEL_WORK_GROUP_SIZE);
  }

  /**
   * @return The OpenCL program that the kernel belongs to.
   */
  public cl_program getProgram() {
    return this.program;
  }

  /**
   * @return the sourceName
   */
  public String getSourceName() {
    return this.sourceName;
  }

  /**
   * Get a long param from the device.
   *
   * @param param
   *            The param desired.
   * @return The param value.
   */
  public long getWorkGroupLong(final int param) {
    final long[] result = new long[1];
    final long[] len = new long[1];

    CL.clGetKernelWorkGroupInfo(this.kernel, this.device.getDevice(),
        param, Sizeof.cl_long, Pointer.to(result), len);
    return result[0];
  }

  /**
   * Called internally to prepare to execute a kernel.
   */
  public void prepareKernel() {
    if (this.kernel == null) {
      throw new EncogEngineError(
          "Must compile CL kernel before using it.");
    }
  }

  /**
   * Release this kernel.
   */
  public void release() {
    if (this.program != null) {
      CL.clReleaseProgram(this.program);
      CL.clReleaseKernel(this.kernel);
      this.program = null;
      this.kernel = null;
    }
  }

  /**
   * Release a buffer.
   * @param mem The buffer to release.
   */
  public void releaseBuffer(final cl_mem mem) {
    CL.clReleaseMemObject(mem);
  }

  /**
   * Set an argument.
   * @param num The argument number.
   * @param mem The memory buffer.
   */
  public void setArg(final int num, final cl_mem mem) {
    CL.clSetKernelArg(getKernel(), num, Sizeof.cl_mem, Pointer.to(mem));
  }

  /**
   * @param cl
   *            the cl to set
   */
  public void setCLSource(final String cl) {
    this.cl = cl;
  }

  /**
   * Set the size of the global work group.
   * @param globalWork The size of the global work group.
   */
  public void setGlobalWork(final int globalWork) {
    this.globalWork = globalWork;
  }

  /**
   * Set the size of the local work group.
   * @param localWork The size of the local work group.
   */
  public void setLocalWork(final int localWork) {
    this.localWork = localWork;
  }

}
TOP

Related Classes of org.encog.engine.opencl.kernels.EncogKernel

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.