content: /*
   * Copyright (C) 2014 - Andreas Maier, Magdalena Herbst, Michael Dorner, Salah Saleh, Anja Pohan, Stefan Nottrott, Frank Schebesch 
   * CONRAD is developed as an Open Source project under the GNU General Public License (GPL).
  */
  package edu.stanford.rsl.conrad.data.numeric.opencl;
  
  import com.jogamp.opencl.CLContext;
  import com.jogamp.opencl.CLDevice;
  
  import edu.stanford.rsl.conrad.data.numeric.Grid2D;
  import edu.stanford.rsl.conrad.opencl.OpenCLUtil;
  
  /**
   * OpenCLBenchmark is a tiny benchmark for testing local and global memory kernels and demo how an extension of new kernels works.
   */
  public class OpenCLBenchmark {
  	
  
  	public static void main(String[] args) {
  		
  		CLContext context = OpenCLUtil.createContext();
  		CLDevice[] devices = context.getDevices();	
  		CLDevice device = devices[0];
  		
  		String leftAlignFormat = "| %-20s | %-5d | %-6d |%n";
  
  		System.out.format("+----------------------+-------+--------+%n");
  		System.out.printf("| size                 | local | global |%n");
  		System.out.format("+----------------------+-------+--------+%n");
  		
  		int iterations = 10;
  		
  		for (int p = 2; p<12; p++)
  		{
  			int x = (int)Math.pow(2, p);
  			int y = (int)Math.pow(2, p);
  			
  			Grid2D grid2D = new Grid2D(x, y);
  			
  			// fill the grid with 1.0f
  			for(int i = 0; i<x; i++) {
  				for(int j = 0; j<y; j++) {
  					float val = 1.0f;
  					grid2D.setAtIndex(i, j, val);
  				}
  			}
  				
  			
  			// local version, using the standard OpenClGridOperators class
  			
  			OpenCLGrid2D openCLGrid2DLocal = new OpenCLGrid2D(grid2D, context, device);
  			OpenCLGridOperators openCLGridOperatos = (OpenCLGridOperators) openCLGrid2DLocal.getGridOperator();
  			openCLGridOperatos.sum(openCLGrid2DLocal); // initialize
  			
  			double sum = 0.0;
  			
  			long startLocal = System.currentTimeMillis();
  			for (int i = 0; i<iterations; i++) 
  			{
  				sum = openCLGridOperatos.sum(openCLGrid2DLocal);
  			}
  			long endLocal = (System.currentTimeMillis() - startLocal);
  			
  
  			if ((int)sum != x*y) {
  				System.out.println("\tWrong result in local sum: " + sum + " != " + x);
  			}
  			
  			openCLGrid2DLocal.release();
  			openCLGrid2DLocal = null;
  			
  
  			/*
  			 * In this example we extend the standard OpenCL grid operators by a new method 'sumGlobalMemory(...)'. 
  			 * Therefore we have to instantiate the new class ExtendedOpenCLGridOperators by its singleton.
  			 * Then we can set this new, extended grid operator class to the grid.
  			 */
  			
  			OpenCLGrid2D openCLGrid2DGlobal = new OpenCLGrid2D(grid2D, context, device);
  			
  			openCLGrid2DGlobal.setNumericGridOperator(ExtendedOpenCLGridOperators.getInstance()); // set a new numeric grid operator class
  			
  			ExtendedOpenCLGridOperators gg = (ExtendedOpenCLGridOperators) openCLGrid2DGlobal.getGridOperator(); // continue as usual, but with a cast
  			gg.sumGlobalMemory(openCLGrid2DGlobal);
  			
  			
  			sum = 0.0;
  
  			long startGlobal = System.currentTimeMillis();
  			for (int i = 0; i<iterations; i++) 
  			{
  				sum = gg.sumGlobalMemory(openCLGrid2DGlobal);
  			}			
  			long endGlobal = (System.currentTimeMillis() - startGlobal);
  			
  			if ( (int)sum != x*y ) {
  				System.out.println("\tWrong result in global sum: " + sum + " != " + x*y);
  			}
  			
  			openCLGrid2DGlobal.release();
  			openCLGrid2DGlobal = null;
  			
  			
  			System.out.format(leftAlignFormat, (x + " x " + y)+ " pixels ", endLocal/iterations, endGlobal/iterations);
  
  				
  		}
  		
  		System.out.format("+----------------------+-------+--------+%n");
  		
  		
  		// last, but not lead: 
  		// dot product
  		Grid2D grid2D = new Grid2D(512, 512);
  		for(int i = 0; i<512; i++) {
  			for(int j = 0; j<512; j++) {
  				float val = 1.0f;
  				grid2D.setAtIndex(i, j, val);
  			}
  		}
  		
  		OpenCLGrid2D openCLGrid2D = new OpenCLGrid2D(grid2D, context, device);
  		double dotProduct = openCLGrid2D.getGridOperator().dotProduct(openCLGrid2D, openCLGrid2D);
  		System.out.println("dot product: " + dotProduct);
  
  		//min
  		openCLGrid2D.setAtIndex(1, 2, -0.12345f);
  		float min = openCLGrid2D.getGridOperator().min(openCLGrid2D);
  		System.out.println("min: " + min);
  		
  
  		
  	}
  }
  