package mior.model; import java.util.Arrays; import mcmas.core.MCMCommandQueue; import mcmas.core.MCMCommandQueueProperty; import mcmas.core.MCMContext; import mcmas.core.MCMEvent; import mcmas.core.MCMKernel; import mcmas.core.MCMMem; import mcmas.core.MCMProgram; import mcmas.core.MCMUtils; import org.jocl.Pointer; import org.perf4j.slf4j.Slf4JStopWatch; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class OCLParaCSRModel2 extends AbstractMiorModel { /** * Java view */ private final int nbMM; private final int nbOM; private final MiorMM [] mmList; private final MiorOM [] omList; private final MiorWorld [] worlds; private final int [] associations; /** * OpenCL implementation */ final MCMContext context; final MCMCommandQueue queue; final MCMProgram program; final MCMKernel topoKernel; final MCMKernel autoliveKernel; final MCMMem mmMem; final MCMMem omMem; final MCMMem worldsMem; /*final OCLMem mmCSRMem; final OCLMem omCSRMem;*/ final MCMMem associationsMem; final MCMMem partsMem; /* private final int [] mmCSR; private final int [] omCSR; */ private final int nbSim; private int blockSize; private final static Logger logger = LoggerFactory.getLogger(OCLParaCSRModel2.class); private final Slf4JStopWatch watch = new Slf4JStopWatch(logger); private final static String MODEL_SOURCE = "kernels/mior_model_multisim2.cl"; public OCLParaCSRModel2(int nbMM, int nbOM, int nbSim) { this.nbSim = nbSim; this.nbMM = nbMM; this.nbOM = nbOM; this.blockSize = Math.max(nbOM, nbMM); // Allocate Java MIOR structures this.mmList = new MiorMM[nbSim * nbMM]; this.omList = new MiorOM[nbSim * nbOM]; this.worlds = new MiorWorld[nbSim]; this.associations = new int[nbSim * nbMM * nbOM]; //final Random rand = new Random(); TODO: Remove // Initialise models for (int i = 0; i < nbSim; i++) { this.worlds[i] = new MiorWorld(nbMM, nbOM); } MiorUtils.initRandomMMArray(mmList, worlds[0].width); MiorUtils.initRandomOMArray(omList, worlds[0].width); Arrays.fill(associations, -1); // OpenCL allocations watch.start("OpenCL setup"); this.context = new MCMContext(); this.queue = context.createCommandQueue(MCMCommandQueueProperty.ENABLE_PROFILING); watch.stop(); watch.start("Program compilation"); this.program = MCMUtils.compileFile(context, MODEL_SOURCE, " -DNB_MM=" + nbMM + " -DNB_OM=" + nbOM);// + " -g -O0"); watch.stop(); watch.start("Kernel allocation"); this.topoKernel = program.createKernel("topology"); this.autoliveKernel = program.createKernel("autolive"); watch.stop(); watch.start("Memory allocation"); this.mmMem = context.newBuffer().Using(mmList).b(); this.omMem = context.newBuffer().Using(omList).b(); this.worldsMem = context.newBuffer().Using(worlds).b(); /*this.mmCSR = allocateStorage(nbOM * nbSim, nbMM); this.mmCSRMem = context.newBuffer().Using(mmCSR).b(); this.omCSR = allocateStorage(nbMM * nbSim, nbOM); this.omCSRMem = context.newBuffer().Using(omCSR).b(); */ this.associationsMem = context.newBuffer().Using(associations).b(); this.partsMem = context.newBuffer().Using(new int[associations.length]).b(); watch.stop(); } @Override public int getNbSimulations() { return nbSim; } @Override protected void resetImpl() { // Initialize models for (int i = 0; i < nbSim; i++) { this.worlds[i] = new MiorWorld(nbMM, nbOM); } MiorUtils.initRandomMMArray(mmList, worlds[0].width); MiorUtils.initRandomOMArray(omList, worlds[0].width); Arrays.fill(associations, -1); queue.enqueueWriteBuffer(mmMem, mmList, 0, mmMem.getSize()); queue.enqueueWriteBuffer(omMem, omList, 0, omMem.getSize()); queue.enqueueWriteBuffer(worldsMem, worlds, 0, worldsMem.getSize()); //queue.enqueueWriteBuffer(mmCSRMem, Pointer.to(mmCSR), 0, mmCSRMem.getSize()); //queue.enqueueWriteBuffer(omCSRMem, Pointer.to(omCSR), 0, omCSRMem.getSize()); queue.enqueueWriteBuffer(associationsMem, Pointer.to(associations), 0, associationsMem.getSize()); queue.finish(); } @Override public void setBlockSize(int blockSize) { this.blockSize = blockSize; } @Override public int getBlockSize() { return blockSize; } @Override protected void doTopologyImpl() { // System.out.println(topoKernel.getArgumentsNumber()); topoKernel.setArguments(mmMem, omMem, worldsMem, associationsMem); MCMEvent event = queue.enqueueKernel(topoKernel, 2, new long[] { nbSim * nbMM , nbOM} ); MCMEvent.waitFor(event); MCMUtils.printEventStats("topology", event); if (! isBatchModeEnabled()) { //queue.blockingReadBuffer(mmCSRMem, Pointer.to(mmCSR), 0, mmCSRMem.getSize()); //queue.blockingReadBuffer(omCSRMem, Pointer.to(omCSR), 0, omCSRMem.getSize()); queue.blockingReadBuffer(associationsMem, Pointer.to(associations), 0, associationsMem.getSize()); } } @Override protected void doLiveImpl() { throw new UnsupportedOperationException(); } @Override public void doAutoLive() { resetImpl(); doTopologyImpl(); autoliveKernel.setArguments(mmMem, omMem, worldsMem, associationsMem, partsMem); /* OCLEvent event = queue.enqueueKernel(autoliveKernel, 2, new long[] { nbSim, Math.max(nbOM, nbMM) } );*/ if (blockSize < Math.max(nbOM, nbMM)) { throw new RuntimeException("blockSize (" + blockSize + ") is too small to execute the simulation"); } //System.out.println("nbAgents: " + nbAgents); MCMEvent event = queue.enqueue1DKernel(autoliveKernel, nbSim * blockSize, blockSize); MCMEvent.waitFor(event); MCMUtils.printEventStats("autolive", event); onSimulationFinished(); } @Override protected void onSimulationFinished() { //if (isBatchModeEnabled()) { queue.blockingReadBuffer(mmMem, mmList, 0, mmMem.getSize()); queue.blockingReadBuffer(omMem, omList, 0, omMem.getSize()); queue.blockingReadBuffer(worldsMem, worlds, 0, worldsMem.getSize()); queue.blockingReadBuffer(associationsMem, Pointer.to(associations), 0, associationsMem.getSize()); //} super.onSimulationFinished(); } @Override protected void releaseImpl() { partsMem.release(); associationsMem.release(); //omCSRMem.release(); //mmCSRMem.release(); worldsMem.release(); omMem.release(); mmMem.release(); autoliveKernel.release(); topoKernel.release(); program.release(); queue.release(); context.release(); } @Override public MiorWorld getWorld() { return worlds[0]; } @Override public MiorOM[] getOMList() { return Arrays.copyOfRange(omList, 0, nbOM); } @Override public MiorMM[] getMMList() { return Arrays.copyOfRange(mmList, 0, nbMM); } @Override public boolean isAccessible(int iMM, int iOM) { return associations[iMM * nbOM + iOM] != -1; } @Override public boolean isAccessible(int iMM, int iOM, int iSim) { return associations[iSim * nbMM * nbOM + iMM * nbOM + iOM] != -1; } }