package org.kne.opencl64;

import java.lang.foreign.Arena;
import java.lang.foreign.MemorySegment;
import java.nio.ByteBuffer;
import java.util.List;

public class TestOpenCL64 {

	public static void main(String[] args) throws InterruptedException {
		stressTest();
		//bandwidthBenchmark();
	}

	private static void bandwidthBenchmark() {
		List<OpenCLPlatform> ocp=OpenCLPlatform.getOpenCLPlatforms();
		for (OpenCLPlatform openCLPlatform : ocp) {
			System.out.println(openCLPlatform);
			List<OpenCLDevice> devices=  openCLPlatform.getOpenCLDevices();
			for (OpenCLDevice openCLDevice : devices) {
				System.out.println(devices);
				for(int i=0;i<10;i++) {
					long length=1024L*1024L*1024L;
				OpenCLContext cont=new OpenCLContext(openCLPlatform, openCLDevice);
				OpenCLCommandQueue queue=new OpenCLCommandQueue(cont, openCLDevice);
				OpenCLMemory ocma=new OpenCLMemory(cont,OpenCLMemoryCopyType.ALLOC_HOST_PTR,length);
				OpenCLMemory ocmb=new OpenCLMemory(cont,OpenCLMemoryCopyType.ALLOC_HOST_PTR,length);
				long start=System.nanoTime();
				queue.executeCopyBuffer(ocma, ocmb, 0, 0, length);
				queue.finish();
				long time=System.nanoTime()-start;
				System.out.println(time);
				
				long start2=System.nanoTime();
				MemorySegment mpa= queue.mapBuffer(ocma, false, OpenCLMapFlag.CL_MAP_READ, 0, length);
				MemorySegment mpb=queue.mapBuffer(ocmb, true, OpenCLMapFlag.CL_MAP_WRITE, 0, length);
				mpb.copyFrom(mpa);
				queue.unmapBuffer(ocma, mpa, false);
				queue.unmapBuffer(ocmb, mpb, true);
				long time2=System.nanoTime()-start2;
				System.out.println(time2);
				
				System.gc();
				}
			}
		}
	}

	private static void stressTest() {
		List<OpenCLPlatform> ocp=OpenCLPlatform.getOpenCLPlatforms();
		for (OpenCLPlatform openCLPlatform : ocp) {
			System.out.println(openCLPlatform);
			List<OpenCLDevice> devices=  openCLPlatform.getOpenCLDevices();
			for (OpenCLDevice openCLDevice : devices) {
				new Thread(()->{
					long length=128;
				OpenCLContext cont=new OpenCLContext(openCLPlatform, openCLDevice);
				
				
				MemorySegment msa=Arena.ofAuto().allocate(length);
				
				
				
				OpenCLMemory ocma=new OpenCLMemory(cont,msa,OpenCLMemoryCopyType.USE_HOST_PTR);
				
				
				MemorySegment msb=Arena.ofAuto().allocate(length);
				OpenCLMemory ocmb=new OpenCLMemory(cont,msb,OpenCLMemoryCopyType.USE_HOST_PTR);

				MemorySegment msc=Arena.ofAuto().allocate(length);
				OpenCLMemory ocmc=new OpenCLMemory(cont,msc,OpenCLMemoryCopyType.USE_HOST_PTR);
				System.out.println("addr:"+msa.address()+" "+ocma.address());
				String programSource =
					        "__kernel void "+
					        "sampleKernel(__global const float *a,"+
					        "             __global const float *b,"+
					        "             __global float *c)"+
					        "{"+
					        "   printf(\"%lld\\n\",a); int gid = get_global_id(0);"+
					        "for(int i=0;i<100;i++)"+
					        "    c[gid] = a[gid] + b[gid];"+
					        "}";
				OpenCLProgram prog= new OpenCLProgram(cont, programSource); 
				prog.buildProgram();
				
				OpenCLKernel kernel= prog.createKernel("sampleKernel");
				kernel.putArg(ocma).putArg(ocmb).putArg(ocmc);
				OpenCLCommandQueue queue=new OpenCLCommandQueue(cont, openCLDevice);
						queue.execute1DRangeKernel(kernel, 0, length/4);
				queue.executeReadBuffer(ocmc,msc,true,0,0,msc.byteSize());
				queue.finish();		
				//Thread.sleep(10000);
				}).start();
			}
		}
	}
}
