001/*
002 * To change this template, choose Tools | Templates
003 * and open the template in the editor.
004 */
005
006package com.nativelibs4java.opencl.util;
007
008import com.nativelibs4java.opencl.CLBuildException;
009import com.nativelibs4java.opencl.CLContext;
010import com.nativelibs4java.opencl.CLBuffer;
011import com.nativelibs4java.opencl.CLEvent;
012import com.nativelibs4java.opencl.CLKernel;
013import com.nativelibs4java.opencl.CLProgram;
014import com.nativelibs4java.opencl.CLQueue;
015import com.nativelibs4java.opencl.JavaCL;
016import com.nativelibs4java.opencl.util.ReductionUtils;
017import com.nativelibs4java.opencl.util.ReductionUtils.Reductor;
018import com.nativelibs4java.util.IOUtils;
019import com.nativelibs4java.util.Pair;
020import static com.nativelibs4java.util.NIOUtils.*;
021import java.io.FileNotFoundException;
022import java.io.IOException;
023import java.io.InputStream;
024import java.io.PrintWriter;
025import java.io.StringWriter;
026import java.util.EnumMap;
027import java.util.HashMap;
028import java.util.Map;
029import java.util.logging.Level;
030import java.util.logging.Logger;
031
032/**
033 *
034 * @author ochafik
035 */
036@SuppressWarnings("unused")
037public class ParallelMath {
038
039    protected CLContext context;
040    protected CLQueue queue;
041
042    public ParallelMath() {
043        this(JavaCL.createBestContext().createDefaultQueue());
044    }
045
046    public ParallelMath(CLQueue queue) {
047        this.queue = queue;
048                CLContext context = queue.getContext();
049    }
050
051    public CLQueue getQueue() {
052        return queue;
053    }
054
055        public CLContext getContext() {
056                return getQueue().getContext();
057        }
058
059    protected String createVectFun1Source(Fun1 function, Primitive type, StringBuilder out) {
060        String t = type.clTypeName();
061        String kernelName = "vect_" + function.name() + "_" + t;// + (inPlace ? "_inplace" : "");
062        out.append("__kernel void " + kernelName + "(\n");
063        out.append("\t__global const " + t + "* in,\n");
064        out.append("\t__global " + t + "* out,\n");
065        out.append("\tlong length\n");
066        out.append(") {\n");
067        out.append("\tint i = get_global_id(0);\n");
068        out.append("\tif (i >= length) return;\n");
069        out.append("\tout[i] = ");
070        function.expr("in[i]", out);
071        out.append(";\n");
072        out.append("}\n");
073        return kernelName;
074    }
075    
076    
077    protected String createVectFun2Source(Fun2 function, Primitive type1, Primitive type2, Primitive typeOut, StringBuilder out, boolean secondOperandIsScalar) {
078        String t1 = type1.clTypeName(), t2 = type2.clTypeName(), to = typeOut.clTypeName();
079        String kernelName = "vect_" + function.name() + "_" + t1 + "_" + t2 + "_" + to;
080        out.append("__kernel void " + kernelName + "(\n");
081        out.append("\t__global const " + t1 + "* in1,\n");
082        if (secondOperandIsScalar)
083            out.append("\t" + t2 + " in2,\n");
084        else
085            out.append("\t__global const " + t2 + "* in2,\n");
086        out.append("\t__global " + to + "* out,\n");
087        out.append("\tlong length\n");
088        out.append(") {\n");
089        out.append("\tint i = get_global_id(0);\n");
090        out.append("\tif (i >= length) return;\n");
091        out.append("\tout[i] = (" + to + ")");
092        function.expr("in1[i]", (secondOperandIsScalar ? "in2" : "in2[i]"), out);
093        out.append(";\n");
094        out.append("}\n");
095        return kernelName;
096    }
097
098
099    private EnumMap<Fun1, EnumMap<Primitive, CLKernel>> fun1Kernels = new EnumMap<Fun1, EnumMap<Primitive, CLKernel>>(Fun1.class);
100
101    
102    public synchronized CLKernel getKernel(Fun1 op, Primitive prim) throws CLBuildException {
103        EnumMap<Primitive, CLKernel> m = fun1Kernels.get(op);
104        if (m == null)
105            fun1Kernels.put(op, m = new EnumMap<Primitive, CLKernel>(Primitive.class));
106
107        CLKernel kers = m.get(prim);
108        if (kers == null) {
109            StringBuilder out = new StringBuilder(300);
110            String name = createVectFun1Source(op, prim, out);
111            CLProgram prog = getContext().createProgram(out.toString()).build();
112            kers = prog.createKernel(name);
113            m.put(prim, kers);
114        }
115        return kers;
116    }
117
118    static class PrimitiveTrio extends Pair<Pair<Primitive, Primitive>, Pair<Primitive, Boolean>> {
119        public PrimitiveTrio(Primitive a, Primitive b, Primitive c, boolean secondOperandIsScalar) {
120            super(new Pair<Primitive, Primitive>(a, b), new Pair<Primitive, Boolean>(c, secondOperandIsScalar));
121        }
122    }
123    private EnumMap<Fun2, Map<PrimitiveTrio, CLKernel>> fun2Kernels = new EnumMap<Fun2, Map<PrimitiveTrio, CLKernel>>(Fun2.class);
124    public synchronized CLKernel getKernel(Fun2 op, Primitive prim, boolean secondOperandIsScalar) throws CLBuildException {
125        return getKernel(op, prim, prim, prim, secondOperandIsScalar);
126    }
127
128    public synchronized CLKernel getKernel(Fun2 op, Primitive prim1, Primitive prim2, Primitive primOut, boolean secondOperandIsScalar) throws CLBuildException {
129        Map<PrimitiveTrio, CLKernel> m = fun2Kernels.get(op);
130        if (m == null)
131            fun2Kernels.put(op, m = new HashMap<PrimitiveTrio, CLKernel>());
132
133        PrimitiveTrio key = new PrimitiveTrio(prim1, prim2, primOut, secondOperandIsScalar);
134        CLKernel ker = m.get(key);
135        if (ker == null) {
136            StringBuilder out = new StringBuilder(300);
137            String name = createVectFun2Source(op, prim1, prim2, primOut, out, secondOperandIsScalar);
138            CLProgram prog = getContext().createProgram(out.toString()).build();
139            ker = prog.createKernel(name);
140            m.put(key, ker);
141        }
142        return ker;
143    }
144    
145}