Package org.encog.plugins.opencl.example

Source Code of org.encog.plugins.opencl.example.DFT

package org.encog.plugins.opencl.example;

import java.io.IOException;
import java.nio.DoubleBuffer;

import org.encog.util.file.ResourceInputStream;

import com.nativelibs4java.opencl.CLBuildException;
import com.nativelibs4java.opencl.CLContext;
import com.nativelibs4java.opencl.CLDoubleBuffer;
import com.nativelibs4java.opencl.CLEvent;
import com.nativelibs4java.opencl.CLKernel;
import com.nativelibs4java.opencl.CLMem;
import com.nativelibs4java.opencl.CLProgram;
import com.nativelibs4java.opencl.CLQueue;
import com.nativelibs4java.opencl.JavaCL;
import com.nativelibs4java.opencl.CLPlatform.DeviceFeature;

public class DFT {

    final CLQueue queue;
    final CLContext context;
    final CLProgram program;
    final CLKernel kernel;

    public DFT(CLQueue queue) throws IOException, CLBuildException {
        this.queue = queue;
        this.context = queue.getContext();

        String source = ResourceInputStream.readResourceAsString("org/encog/plugins/opencl/kernels/DiscreteFourierTransformProgram.cl");

        program = context.createProgram(source);
        kernel = program.createKernel("dft");
    }

    /**
* Method that takes complex values in input (sequence of pairs of real and imaginary values) and
* returns the Discrete Fourier Transform of these values if forward == true or the inverse
* transform if forward == false.
*/
    public synchronized DoubleBuffer dft(DoubleBuffer in, boolean forward) {
        assert in.capacity() % 2 == 0;
        int length = in.capacity() / 2;

        // Create an input CLBuffer that will be a copy of the NIO buffer :
        CLDoubleBuffer inBuf = context.createDoubleBuffer(CLMem.Usage.Input, in, true); // true = copy
       
        // Create an output CLBuffer :
        CLDoubleBuffer outBuf = context.createDoubleBuffer(CLMem.Usage.Output, length * 2);

        // Set the args of the kernel :
        kernel.setArgs(inBuf, outBuf, length, forward ? 1 : -1);
       
        // Ask for `length` parallel executions of the kernel in 1 dimension :
        CLEvent dftEvt = kernel.enqueueNDRange(queue, new int[]{ length });

        // Return an NIO buffer read from the output CLBuffer :
        return outBuf.read(queue, dftEvt);
    }

    /// Wrapper method that takes and returns double arrays
    public double[] dft(double[] complexValues, boolean forward) {
        DoubleBuffer outBuffer = dft(DoubleBuffer.wrap(complexValues), forward);
        double[] out = new double[complexValues.length];
        outBuffer.get(out);
        return out;
    }

    public static void main(String[] args) throws IOException, CLBuildException {
     // Create a context with the best double numbers support possible :
     // (try using DeviceFeature.GPU, DeviceFeature.CPU...)
        CLContext context = JavaCL.createBestContext(DeviceFeature.DoubleSupport);
       
        // Create a command queue, if possible able to execute multiple jobs in parallel
        // (out-of-order queues will still respect the CLEvent chaining)
        CLQueue queue = context.createDefaultOutOfOrderQueueIfPossible();

        DFT dft = new DFT(queue);
        //DFT2 dft = new DFT2(queue);

        // Create some fake test data :
        double[] in = createTestDoubleData();

        // Transform the data (spatial -> frequency transform) :
        double[] transformed = dft.dft(in, true);
       
        for (int i = 0; i < transformed.length / 2; i++) {
            // Print the transformed complex values (real + i * imaginary)
            System.out.println(transformed[i * 2] + "\t + \ti * " + transformed[i * 2 + 1]);
        }
       
        // Reverse-transform the transformed data (frequency -> spatial transform) :
        double[] backTransformed = dft.dft(transformed, false);

        // Check the transform + inverse transform give the original data back :
        double precision = 1e-5;
        for (int i = 0; i < in.length; i++) {
            if (Math.abs(in[i] - backTransformed[i]) > precision)
                throw new RuntimeException("Different values in back-transformed array than in original array !");
        }
    }

    static double[] createTestDoubleData() {
        int n = 32;
        double[] in = new double[2 * n];

        for (int i = 0; i < n; i++) {
            in[i * 2] = 1 / (double) (i + 1);
            in[i * 2 + 1] = 0;
        }
        return in;
    }
}

TOP

Related Classes of org.encog.plugins.opencl.example.DFT

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.