/******************************************************************************* * TurtleKit 3 - Agent Based and Artificial Life Simulation Platform * Copyright (C) 2011-2014 Fabien Michel * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. ******************************************************************************/ package turtlekit.cuda; import static jcuda.driver.JCudaDriver.cuMemAlloc; import static jcuda.driver.JCudaDriver.cuMemFree; import static jcuda.driver.JCudaDriver.cuMemFreeHost; import java.nio.FloatBuffer; import java.util.concurrent.ExecutionException; import jcuda.Pointer; import jcuda.Sizeof; import jcuda.driver.CUDA_ARRAY_DESCRIPTOR; import jcuda.driver.CUDA_MEMCPY2D; import jcuda.driver.CUarray; import jcuda.driver.CUarray_format; import jcuda.driver.CUdeviceptr; import jcuda.driver.CUmemorytype; import jcuda.driver.CUstream; import jcuda.driver.CUstream_flags; import jcuda.driver.JCudaDriver; import turtlekit.pheromone.AbstractPheromoneGrid; import turtlekit.pheromone.Pheromone; public class CudaPheromone extends AbstractPheromoneGrid<Float> implements CudaObject,Pheromone<Float>{ private FloatBuffer values; // private float[] arr; /** * @return the values */ public FloatBuffer getValues() { return values; } /** * @param values the values to set */ public void setValues(FloatBuffer values) { this.values = values; } CUdeviceptr valuesPtr; CUdeviceptr tmpDeviceDataGrid; private Pointer valuesPinnedMemory; protected Pointer arrPointer; protected CUdeviceptr testDevicePtr; protected Pointer heightPtr; protected Pointer dataGridPtr; private CudaKernel diffusionToTmpKernel; private CudaKernel diffusionUpdateKernel; private CudaKernel diffusionUpdateThenEvaporationKernel; private CudaKernel evaporationKernel; protected Pointer widthPtr; private KernelConfiguration kernelConfiguration; protected Pointer tmpDeviceDataGridPtr; public KernelConfiguration getKernelConfiguration() { return kernelConfiguration; } public void setKernelConfiguration(KernelConfiguration kernelConfiguration) { this.kernelConfiguration = kernelConfiguration; } public CudaPheromone(String name, int width, int height, final int evapPercentage, final int diffPercentage) { this(name, width, height, evapPercentage / 100f, diffPercentage / 100f); } public CudaPheromone(String name, int width, int height, final float evapPercentage, final float diffPercentage) { super(name, width, height, evapPercentage, diffPercentage); setMaximum(0f); widthPtr = getPointerToInt(width); heightPtr = getPointerToInt(height); tmpDeviceDataGrid = createDeviceDataGrid(Float.class); tmpDeviceDataGridPtr = Pointer.to(tmpDeviceDataGrid); valuesPtr = new CUdeviceptr(); valuesPinnedMemory = new Pointer(); values = (FloatBuffer) getUnifiedBufferBetweenPointer(valuesPinnedMemory, valuesPtr, Float.class); dataGridPtr = Pointer.to(valuesPinnedMemory); initKernels(); } protected void initKernels() { kernelConfiguration = getNewKernelConfiguration(); // kernelConfiguration.setStreamID(cudaEngine.getNewCudaStream()); diffusionToTmpKernel = getCudaKernel("DIFFUSION_TO_TMP", "/turtlekit/cuda/kernels/Diffusion_2D.cu", kernelConfiguration); diffusionUpdateKernel = getCudaKernel("DIFFUSION_UPDATE", "/turtlekit/cuda/kernels/Diffusion_2D.cu", kernelConfiguration); diffusionUpdateThenEvaporationKernel = getCudaKernel("DIFFUSION_UPDATE_THEN_EVAPORATION", "/turtlekit/cuda/kernels/DiffusionEvaporation_2D.cu", kernelConfiguration); evaporationKernel = getCudaKernel("EVAPORATION", "/turtlekit/cuda/kernels/Evaporation_2D.cu", kernelConfiguration); } @Override public Float get(int index) { return values.get(index); } @Override public void set(int index, Float value) { if(value > getMaximum()) setMaximum(value); values.put(index, value); } protected void diffuseValuesToTmpGridKernel(){ diffusionToTmpKernel.run( widthPtr, heightPtr, dataGridPtr, tmpDeviceDataGridPtr, getPointerToFloat(getDiffusionCoefficient())); } @Override protected void diffusionUpdateKernel() { diffusionUpdateKernel.run( widthPtr, heightPtr, dataGridPtr, tmpDeviceDataGridPtr); } @Override public void diffusionAndEvaporationUpdateKernel() { diffusionUpdateThenEvaporationKernel.run( widthPtr, heightPtr, dataGridPtr, tmpDeviceDataGridPtr, getPointerToFloat(getEvaporationCoefficient())); } @Override public void evaporationKernel() { evaporationKernel.run( widthPtr, heightPtr, dataGridPtr, getPointerToFloat(getEvaporationCoefficient())); } public void freeMemory() { freeCudaMemory(tmpDeviceDataGrid); freeCudaMemory(valuesPinnedMemory); freeCudaMemory(valuesPtr); } /** * @return the valuesPtr */ public CUdeviceptr getValuesPtr() { return valuesPtr; } /** * @param valuesPtr the valuesPtr to set */ public void setValuesPtr(CUdeviceptr valuesPtr) { this.valuesPtr = valuesPtr; } /** * @return the valuesPinnedMemory */ public Pointer getValuesPinnedMemory() { return valuesPinnedMemory; } /** * @param valuesPinnedMemory the valuesPinnedMemory to set */ public void setValuesPinnedMemory(Pointer valuesPinnedMemory) { this.valuesPinnedMemory = valuesPinnedMemory; } @Override public void incValue(int x, int y, float quantity) { incValue(get1DIndex(x, y), quantity); } /** * Adds <code>inc</code> to the current value of the cell * with the corresponding index * * @param index cell's index * @param inc how much to add */ public void incValue(int index, float inc) { // inc += get(index); // if (inc > maximum) // setMaximum(inc); // set(index, inc); set(index, inc + get(index)); } public int getMaxDirection(int xcor, int ycor) { float max = get(normeValue(xcor + 1, getWidth()), ycor); int maxDir = 0; float current = get(normeValue(xcor + 1, getWidth()), normeValue(ycor + 1, getHeight())); if (current > max) { max = current; maxDir = 45; } current = get(xcor, normeValue(ycor + 1, getHeight())); if (current > max) { max = current; maxDir = 90; } current = get(normeValue(xcor - 1, getWidth()), normeValue(ycor + 1, getHeight())); if (current > max) { max = current; maxDir = 135; } current = get(normeValue(xcor - 1, getWidth()), ycor); if (current > max) { max = current; maxDir = 180; } current = get(normeValue(xcor - 1, getWidth()), normeValue(ycor - 1, getHeight())); if (current > max) { max = current; maxDir = 225; } current = get(xcor, normeValue(ycor - 1, getHeight())); if (current > max) { max = current; maxDir = 270; } current = get(normeValue(xcor + 1, getWidth()), normeValue(ycor - 1, getHeight())); if (current > max) { max = current; maxDir = 315; } return maxDir; } public int getMinDirection(int i, int j) { float min = get(normeValue(i + 1, getWidth()), j); int minDir = 0; float current = get(normeValue(i + 1, getWidth()), normeValue(j + 1, getHeight())); if (current < min) { min = current; minDir = 45; } current = get(i, normeValue(j + 1, getHeight())); if (current < min) { min = current; minDir = 90; } current = get(normeValue(i - 1, getWidth()), normeValue(j + 1, getHeight())); if (current < min) { min = current; minDir = 135; } current = get(normeValue(i - 1, getWidth()), j); if (current < min) { min = current; minDir = 180; } current = get(normeValue(i - 1, getWidth()), normeValue(j - 1, getHeight())); if (current < min) { min = current; minDir = 225; } current = get(i, normeValue(j - 1, getHeight())); if (current < min) { min = current; minDir = 270; } current = get(normeValue(i + 1, getWidth()), normeValue(j - 1, getHeight())); if (current < min) { min = current; minDir = 315; } return minDir; } }