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.CLBuffer; 009import com.nativelibs4java.opencl.CLBuildException; 010import com.nativelibs4java.opencl.CLContext; 011import com.nativelibs4java.opencl.CLBuffer; 012import com.nativelibs4java.opencl.CLEvent; 013import com.nativelibs4java.opencl.CLKernel; 014import com.nativelibs4java.opencl.CLPlatform.DeviceFeature; 015import com.nativelibs4java.opencl.CLProgram; 016import com.nativelibs4java.opencl.CLQueue; 017import com.nativelibs4java.opencl.JavaCL; 018import com.nativelibs4java.opencl.util.ReductionUtils; 019import com.nativelibs4java.opencl.util.ReductionUtils.Reductor; 020import com.nativelibs4java.util.IOUtils; 021import com.nativelibs4java.util.Pair; 022import java.io.FileNotFoundException; 023import java.io.IOException; 024import java.io.InputStream; 025import java.io.PrintWriter; 026import java.io.StringWriter; 027import java.nio.Buffer; 028import java.nio.DoubleBuffer; 029import java.util.EnumMap; 030import java.util.HashMap; 031import java.util.Map; 032import java.util.logging.Level; 033import java.util.logging.Logger; 034 035/** 036 * 037 * @author ochafik 038 */ 039@SuppressWarnings("unused") 040public class LinearAlgebraUtils { 041 042 final LinearAlgebraKernels kernels; 043 final CLQueue queue; 044 public LinearAlgebraUtils(boolean doubleCapable) throws IOException, CLBuildException { 045 this(JavaCL.createBestContext(doubleCapable ? DeviceFeature.DoubleSupport : null).createDefaultQueue()); 046 } 047 048 public LinearAlgebraUtils(CLQueue queue) throws IOException, CLBuildException { 049 this.queue = queue; 050 kernels = new LinearAlgebraKernels(queue.getContext()); 051 } 052 053 public CLContext getContext() { 054 return getQueue().getContext(); 055 } 056 057 public CLQueue getQueue() { 058 return queue; 059 } 060 061 public synchronized <T> CLEvent multiply( 062 CLBuffer<T> a, int aRows, int aColumns, 063 CLBuffer<T> b, int bRows, int bColumns, 064 CLBuffer<T> out, //long outRows, long outColumns, 065 CLEvent... eventsToWaitFor) throws CLBuildException 066 { 067 if (a.getElementClass() == Double.class) 068 return multiplyDoubles((CLBuffer<Double>)a, aRows, aColumns, (CLBuffer<Double>)b, bRows, bColumns, (CLBuffer<Double>)out, eventsToWaitFor); 069 if (a.getElementClass() == Float.class) 070 return multiplyFloats((CLBuffer<Float>)a, aRows, aColumns, (CLBuffer<Float>)b, bRows, bColumns, (CLBuffer<Float>)out, eventsToWaitFor); 071 072 throw new UnsupportedOperationException(); 073 } 074 public synchronized CLEvent multiplyDoubles( 075 CLBuffer<Double> a, int aRows, int aColumns, 076 CLBuffer<Double> b, int bRows, int bColumns, 077 CLBuffer<Double> out, //long outRows, long outColumns, 078 CLEvent... eventsToWaitFor) throws CLBuildException 079 { 080 if (a == null || b == null || out == null) 081 throw new IllegalArgumentException("Null matrix"); 082 083 if (aColumns != bRows || out.getElementCount() != (aRows * bColumns)) 084 throw new IllegalArgumentException("Invalid matrix sizes : multiplying matrices of sizes (A, B) and (B, C) requires output of size (A, C)"); 085 086 long outRows = aRows; 087 long outColumns = bColumns; 088 return kernels.mulMatDouble(queue, 089 a, (int)aColumns, 090 b, (int)bColumns, 091 out, 092 new int[] { (int)outRows, (int)outColumns }, 093 null, 094 eventsToWaitFor 095 ); 096 } 097 public synchronized CLEvent multiplyFloats( 098 CLBuffer<Float> a, long aRows, long aColumns, 099 CLBuffer<Float> b, long bRows, long bColumns, 100 CLBuffer<Float> out, //long outRows, long outColumns, 101 CLEvent... eventsToWaitFor) throws CLBuildException 102 { 103 long outRows = aRows; 104 long outColumns = bColumns; 105 return kernels.mulMatFloat(queue, 106 a, (int)aColumns, 107 b, (int)bColumns, 108 out, 109 new int[] { (int)outRows, (int)outColumns }, 110 null, 111 eventsToWaitFor 112 ); 113 } 114 Reductor<Double> addReductorDouble; 115 synchronized Reductor<Double> getAddReductorDouble() { 116 if (addReductorDouble == null) { 117 try { 118 addReductorDouble = ReductionUtils.createReductor(getContext(), ReductionUtils.Operation.Add, OpenCLType.Double, 1); 119 } catch (CLBuildException ex) { 120 Logger.getLogger(LinearAlgebraUtils.class.getName()).log(Level.SEVERE, null, ex); 121 throw new RuntimeException("Failed to create an addition reductor !", ex); 122 } 123 } 124 return addReductorDouble; 125 } 126 127 public synchronized CLEvent transposeDouble(CLBuffer<Double> a, int aRows, int aColumns, CLBuffer<Double> out, CLEvent... eventsToWaitFor) throws CLBuildException { 128 return kernels.transposeDouble(queue, 129 a, aRows, aColumns, 130 out, 131 new int[] { (int)aColumns, (int)aRows }, 132 null, 133 eventsToWaitFor 134 ); 135 } 136 Reductor<Float> addReductorFloat; 137 synchronized Reductor<Float> getAddReductorFloat() { 138 if (addReductorFloat == null) { 139 try { 140 addReductorFloat = ReductionUtils.createReductor(getContext(), ReductionUtils.Operation.Add, OpenCLType.Float, 1); 141 } catch (CLBuildException ex) { 142 Logger.getLogger(LinearAlgebraUtils.class.getName()).log(Level.SEVERE, null, ex); 143 throw new RuntimeException("Failed to create an addition reductor !", ex); 144 } 145 } 146 return addReductorFloat; 147 } 148 149 public synchronized <T> CLEvent transpose(CLBuffer<T> a, int aRows, int aColumns, CLBuffer<T> out, CLEvent... eventsToWaitFor) throws CLBuildException { 150 if (a.getElementClass() == Double.class) 151 return transposeDoubles((CLBuffer<Double>)a, aRows, aColumns, (CLBuffer<Double>)out, eventsToWaitFor); 152 if (a.getElementClass() == Float.class) 153 return transposeFloats((CLBuffer<Float>)a, aRows, aColumns, (CLBuffer<Float>)out, eventsToWaitFor); 154 155 throw new UnsupportedOperationException(); 156 } 157 158 public synchronized CLEvent transposeFloats(CLBuffer<Float> a, int aRows, int aColumns, CLBuffer<Float> out, CLEvent... eventsToWaitFor) throws CLBuildException { 159 return kernels.transposeFloat(queue, 160 a, aRows, aColumns, 161 out, 162 new int[] { (int)aColumns, (int)aRows }, 163 null, 164 eventsToWaitFor 165 ); 166 } 167 168 169 public synchronized CLEvent transposeDoubles(CLBuffer<Double> a, int aRows, int aColumns, CLBuffer<Double> out, CLEvent... eventsToWaitFor) throws CLBuildException { 170 return kernels.transposeDouble(queue, 171 a, aRows, aColumns, 172 out, 173 new int[] { (int)aColumns, (int)aRows }, 174 null, 175 eventsToWaitFor 176 ); 177 } 178 179 180}