Search in sources :

Example 6 with ComponentException

use of com.simiacryptus.mindseye.lang.ComponentException in project MindsEye by SimiaCryptus.

the class SimpleConvolutionLayer method evalAndFree.

@Nullable
@Override
public Result evalAndFree(@Nonnull final Result... inObj) {
    if (!CudaSystem.isEnabled())
        return getCompatibilityLayer().eval(inObj);
    final Result input = inObj[0];
    final TensorList inputData = input.getData();
    @Nonnull final int[] inputSize = inputData.getDimensions();
    @Nonnull final int[] kernelSize = kernel.getDimensions();
    final int[] outputSize = getOutputSize(inputSize);
    final int length = inputData.length();
    kernel.addRef();
    SimpleConvolutionLayer.this.addRef();
    return new Result(CudaSystem.run(gpu -> {
        assert CudaDevice.isThreadDeviceId(gpu.getDeviceId());
        @Nullable final CudaTensor inputTensor = gpu.getTensor(inputData, precision, MemoryType.Device, false);
        final CudaResource<cudnnFilterDescriptor> filterDescriptor = gpu.newFilterDescriptor(precision, cudnnTensorFormat.CUDNN_TENSOR_NCHW, outputSize[2], inputSize[2], kernelSize[1], kernelSize[0]);
        final CudaResource<cudnnConvolutionDescriptor> convolutionDescriptor = gpu.newConvolutions2dDescriptor(cudnnConvolutionMode.CUDNN_CONVOLUTION, precision, paddingY, paddingX, strideY, strideX, 1, 1);
        final int[] outputDims = IntStream.of(reverse(CudaSystem.getOutputDims(inputTensor.descriptor.getPtr(), filterDescriptor.getPtr(), convolutionDescriptor.getPtr()))).limit(3).toArray();
        final CudaDevice.CudaTensorDescriptor outputDescriptor = gpu.newTensorDescriptor(precision, length, outputDims[2], outputDims[1], outputDims[0], outputDims[2] * outputDims[1] * outputDims[0], outputDims[1] * outputDims[0], outputDims[0], 1);
        final int forwardAlgorithm = getForwardAlgorithm(gpu, inputTensor, filterDescriptor, convolutionDescriptor, outputDescriptor);
        final CudaMemory forwardWorkspace = gpu.allocateForwardWorkspace(inputTensor.descriptor.getPtr(), filterDescriptor.getPtr(), convolutionDescriptor.getPtr(), outputDescriptor.getPtr(), forwardAlgorithm, 1);
        try {
            assert 0 < kernel.getData().length;
            assert kernelSize[0] * kernelSize[1] * kernelSize[2] == kernel.getData().length;
            @Nonnull CudaMemory filterPtr = getCudaFilter(gpu);
            @Nonnull final CudaMemory outputBuffer = gpu.allocate((long) Tensor.length(outputDims) * length * precision.size, MemoryType.Managed.normalize(), true);
            CudaMemory inputTensorMemory = inputTensor.getMemory(gpu);
            // inputTensorMemory.synchronize();
            CudaSystem.handle(gpu.cudnnConvolutionForward(precision.getPointer(1.0), inputTensor.descriptor.getPtr(), inputTensorMemory.getPtr(), filterDescriptor.getPtr(), filterPtr.getPtr(), convolutionDescriptor.getPtr(), forwardAlgorithm, null == forwardWorkspace ? null : forwardWorkspace.getPtr(), null == forwardWorkspace ? 0 : forwardWorkspace.size, precision.getPointer(0.0), outputDescriptor.getPtr(), outputBuffer.getPtr()));
            assert CudaDevice.isThreadDeviceId(gpu.getDeviceId());
            forwardWorkspace.dirty();
            filterPtr.dirty();
            outputBuffer.dirty();
            inputTensorMemory.dirty();
            // inputTensorMemory.synchronize();
            inputTensorMemory.freeRef();
            filterPtr.freeRef();
            outputDescriptor.addRef();
            return CudaTensorList.wrap(CudaTensor.wrap(outputBuffer, outputDescriptor, precision), length, outputDims, precision);
        } catch (@Nonnull final Throwable e) {
            throw new ComponentException(String.format("Error in convolution %s x %s", Arrays.toString(inputSize), Arrays.toString(kernelSize)), e);
        } finally {
            Stream.of(inputTensor, filterDescriptor, outputDescriptor, forwardWorkspace, convolutionDescriptor).forEach(ReferenceCounting::freeRef);
        }
    }, inputData), (@Nonnull final DeltaSet<Layer> buffer, @Nonnull final TensorList delta) -> {
        delta.assertAlive();
        buffer.assertAlive();
        inputData.assertAlive();
        assert delta.length() == length;
        delta.addRef();
        Runnable learnFn = () -> {
            if (!isFrozen()) {
                @Nonnull final Tensor weightGradient = CudaSystem.run(gpu -> {
                    @Nullable final CudaTensor deltaTensor = gpu.getTensor(delta, precision, MemoryType.Device, true);
                    delta.freeRef();
                    @Nullable final CudaTensor inputTensor = gpu.getTensor(inputData, precision, MemoryType.Device, false);
                    final CudaResource<cudnnFilterDescriptor> filterDescriptor = gpu.newFilterDescriptor(precision, cudnnTensorFormat.CUDNN_TENSOR_NCHW, outputSize[2], inputSize[2], kernelSize[1], kernelSize[0]);
                    final CudaResource<cudnnConvolutionDescriptor> convolutionDescriptor = gpu.newConvolutions2dDescriptor(cudnnConvolutionMode.CUDNN_CONVOLUTION, precision, paddingY, paddingX, strideY, strideX, 1, 1);
                    final int backwardFilterAlgorithm = getBackwardFilterAlgorithm(gpu, deltaTensor, inputTensor, filterDescriptor, convolutionDescriptor);
                    final CudaMemory backwardsFilterWorkSpace = gpu.allocateBackwardFilterWorkspace(inputTensor.descriptor.getPtr(), filterDescriptor.getPtr(), convolutionDescriptor.getPtr(), deltaTensor.descriptor.getPtr(), backwardFilterAlgorithm, 1);
                    @Nonnull CudaMemory filterPtr = gpu.allocate((long) kernel.length() * precision.size, MemoryType.Device, true);
                    try {
                        CudaMemory inputTensorMemory = inputTensor.getMemory(gpu);
                        CudaMemory deltaTensorMemory = deltaTensor.getMemory(gpu, MemoryType.Managed.normalize());
                        // inputTensorMemory.synchronize();
                        CudaSystem.handle(gpu.cudnnConvolutionBackwardFilter(precision.getPointer(1.0), inputTensor.descriptor.getPtr(), inputTensorMemory.getPtr(), deltaTensor.descriptor.getPtr(), deltaTensorMemory.getPtr(), convolutionDescriptor.getPtr(), backwardFilterAlgorithm, backwardsFilterWorkSpace.getPtr(), backwardsFilterWorkSpace.size, precision.getPointer(0.0), filterDescriptor.getPtr(), filterPtr.getPtr()));
                        filterPtr.dirty();
                        deltaTensorMemory.dirty();
                        inputTensorMemory.dirty();
                        backwardsFilterWorkSpace.dirty();
                        // backwardsFilterWorkSpace.synchronize();
                        inputTensorMemory.freeRef();
                        deltaTensorMemory.freeRef();
                        return filterPtr.read(precision, kernel.getDimensions());
                    } catch (@Nonnull final Throwable e) {
                        throw new ComponentException(String.format("Error in convolution %s x %s => %s", Arrays.toString(inputSize), Arrays.toString(kernelSize), Arrays.toString(outputSize)), e);
                    } finally {
                        inputTensor.freeRef();
                        filterPtr.freeRef();
                        deltaTensor.freeRef();
                        Stream.of(filterDescriptor, convolutionDescriptor, backwardsFilterWorkSpace).forEach(ReferenceCounting::freeRef);
                    }
                }, delta);
                buffer.get(SimpleConvolutionLayer.this, kernel.getData()).addInPlace(weightGradient.getData()).freeRef();
                weightGradient.freeRef();
                clearCudaFilters();
            } else {
                delta.freeRef();
            }
        };
        Runnable backpropFn = () -> {
            if (input.isAlive()) {
                final TensorList inputBufferTensors = CudaSystem.run(gpu -> {
                    final CudaDevice.CudaTensorDescriptor inputDescriptor = gpu.newTensorDescriptor(precision, length, inputSize[2], inputSize[1], inputSize[0], inputSize[2] * inputSize[1] * inputSize[0], inputSize[1] * inputSize[0], inputSize[0], 1);
                    final CudaResource<cudnnFilterDescriptor> filterDescriptor = gpu.newFilterDescriptor(precision, cudnnTensorFormat.CUDNN_TENSOR_NCHW, outputSize[2], inputSize[2], kernelSize[1], kernelSize[0]);
                    final CudaResource<cudnnConvolutionDescriptor> convolutionDescriptor = gpu.newConvolutions2dDescriptor(cudnnConvolutionMode.CUDNN_CONVOLUTION, precision, paddingY, paddingX, strideY, strideX, 1, 1);
                    @Nullable final CudaTensor deltaTensor = gpu.getTensor(delta, precision, MemoryType.Device, false);
                    delta.freeRef();
                    final int backwardDataAlgorithm = getBackwardDataAlgorithm(gpu, inputDescriptor, filterDescriptor, convolutionDescriptor, deltaTensor);
                    final CudaMemory backwardsDataWorkSpace = gpu.allocateBackwardDataWorkspace(inputDescriptor.getPtr(), filterDescriptor.getPtr(), convolutionDescriptor.getPtr(), deltaTensor.descriptor.getPtr(), backwardDataAlgorithm, 1);
                    @Nonnull final CudaMemory filterPtr = getCudaFilter(gpu);
                    try {
                        @Nonnull final CudaMemory passbackMemory = gpu.allocate((long) Tensor.length(inputData.getDimensions()) * length * precision.size, MemoryType.Managed.normalize(), true);
                        CudaMemory deltaTensorMemory = deltaTensor.getMemory(gpu);
                        // deltaTensorMemory.synchronize();
                        CudaSystem.handle(gpu.cudnnConvolutionBackwardData(precision.getPointer(1.0), filterDescriptor.getPtr(), filterPtr.getPtr(), deltaTensor.descriptor.getPtr(), deltaTensorMemory.getPtr(), convolutionDescriptor.getPtr(), backwardDataAlgorithm, backwardsDataWorkSpace.getPtr(), backwardsDataWorkSpace.size, precision.getPointer(0.0), inputDescriptor.getPtr(), passbackMemory.getPtr()));
                        passbackMemory.dirty();
                        backwardsDataWorkSpace.dirty();
                        deltaTensorMemory.dirty();
                        // deltaTensorMemory.synchronize();
                        filterPtr.dirty();
                        deltaTensorMemory.freeRef();
                        inputDescriptor.addRef();
                        return CudaTensorList.wrap(CudaTensor.wrap(passbackMemory, inputDescriptor, precision), length, inputSize, precision);
                    } catch (@Nonnull final Throwable e) {
                        throw new ComponentException(String.format("Error in convolution %s x %s => %s", Arrays.toString(inputSize), Arrays.toString(kernelSize), Arrays.toString(outputSize)), e);
                    } finally {
                        filterPtr.freeRef();
                        deltaTensor.freeRef();
                        Stream.of(inputDescriptor, filterDescriptor, convolutionDescriptor, backwardsDataWorkSpace).forEach(ReferenceCounting::freeRef);
                    }
                }, delta);
                if (null != inputBufferTensors) {
                    input.accumulate(buffer, inputBufferTensors);
                }
            } else {
                delta.freeRef();
            }
        };
        Stream.of(learnFn, backpropFn).forEach(Runnable::run);
    }) {

        @Override
        public final void accumulate(DeltaSet<Layer> buffer, TensorList delta) {
            getAccumulator().accept(buffer, delta);
        }

        @Override
        protected void _free() {
            kernel.freeRef();
            inputData.freeRef();
            Arrays.stream(inObj).forEach(ReferenceCounting::freeRef);
            SimpleConvolutionLayer.this.freeRef();
        }

        @Override
        public boolean isAlive() {
            return input.isAlive() || !isFrozen();
        }
    };
}
Also used : IntStream(java.util.stream.IntStream) JsonObject(com.google.gson.JsonObject) Coordinate(com.simiacryptus.mindseye.lang.Coordinate) Arrays(java.util.Arrays) CudaMemory(com.simiacryptus.mindseye.lang.cudnn.CudaMemory) LoggerFactory(org.slf4j.LoggerFactory) Tensor(com.simiacryptus.mindseye.lang.Tensor) jcuda.jcudnn.cudnnConvolutionMode(jcuda.jcudnn.cudnnConvolutionMode) Result(com.simiacryptus.mindseye.lang.Result) DataSerializer(com.simiacryptus.mindseye.lang.DataSerializer) JsonElement(com.google.gson.JsonElement) Precision(com.simiacryptus.mindseye.lang.cudnn.Precision) CudnnHandle(com.simiacryptus.mindseye.lang.cudnn.CudnnHandle) Map(java.util.Map) jcuda.jcudnn.cudnnConvolutionDescriptor(jcuda.jcudnn.cudnnConvolutionDescriptor) Layer(com.simiacryptus.mindseye.lang.Layer) ReferenceCounting(com.simiacryptus.mindseye.lang.ReferenceCounting) Nonnull(javax.annotation.Nonnull) Nullable(javax.annotation.Nullable) CudaResource(com.simiacryptus.mindseye.lang.cudnn.CudaResource) Util(com.simiacryptus.util.Util) jcuda.jcudnn.cudnnConvolutionBwdDataAlgo(jcuda.jcudnn.cudnnConvolutionBwdDataAlgo) CudaSettings(com.simiacryptus.mindseye.lang.cudnn.CudaSettings) ComponentException(com.simiacryptus.mindseye.lang.ComponentException) Logger(org.slf4j.Logger) CudaDevice(com.simiacryptus.mindseye.lang.cudnn.CudaDevice) CudaTensor(com.simiacryptus.mindseye.lang.cudnn.CudaTensor) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) jcuda.jcudnn.cudnnFilterDescriptor(jcuda.jcudnn.cudnnFilterDescriptor) CudaTensorList(com.simiacryptus.mindseye.lang.cudnn.CudaTensorList) Collectors(java.util.stream.Collectors) List(java.util.List) LayerBase(com.simiacryptus.mindseye.lang.LayerBase) Stream(java.util.stream.Stream) CudaSystem(com.simiacryptus.mindseye.lang.cudnn.CudaSystem) ToDoubleFunction(java.util.function.ToDoubleFunction) TensorList(com.simiacryptus.mindseye.lang.TensorList) DoubleSupplier(java.util.function.DoubleSupplier) MemoryType(com.simiacryptus.mindseye.lang.cudnn.MemoryType) DeltaSet(com.simiacryptus.mindseye.lang.DeltaSet) jcuda.jcudnn.cudnnTensorFormat(jcuda.jcudnn.cudnnTensorFormat) CudaTensor(com.simiacryptus.mindseye.lang.cudnn.CudaTensor) Tensor(com.simiacryptus.mindseye.lang.Tensor) CudaTensor(com.simiacryptus.mindseye.lang.cudnn.CudaTensor) Nonnull(javax.annotation.Nonnull) CudaMemory(com.simiacryptus.mindseye.lang.cudnn.CudaMemory) DeltaSet(com.simiacryptus.mindseye.lang.DeltaSet) CudaTensorList(com.simiacryptus.mindseye.lang.cudnn.CudaTensorList) TensorList(com.simiacryptus.mindseye.lang.TensorList) Result(com.simiacryptus.mindseye.lang.Result) ReferenceCounting(com.simiacryptus.mindseye.lang.ReferenceCounting) CudaResource(com.simiacryptus.mindseye.lang.cudnn.CudaResource) ComponentException(com.simiacryptus.mindseye.lang.ComponentException) Nullable(javax.annotation.Nullable)

Example 7 with ComponentException

use of com.simiacryptus.mindseye.lang.ComponentException in project MindsEye by SimiaCryptus.

the class SoftmaxActivationLayer method evalAndFree.

@Nullable
@Override
public Result evalAndFree(@Nonnull final Result... inObj) {
    if (!CudaSystem.isEnabled())
        return getCompatibilityLayer().evalAndFree(inObj);
    final Result inputResult = inObj[0];
    final TensorList inputData = inputResult.getData();
    @Nonnull final int[] inputSize = inputData.getDimensions();
    @Nonnull final int[] outputSize = inputSize;
    final int length = inputData.length();
    final int inputDims = Tensor.length(inputSize);
    try {
        final CudaTensor outPtr = CudaSystem.run(gpu -> {
            @Nullable CudaTensor inputTensor = gpu.getTensor(inputData, precision, MemoryType.Device, false);
            final CudaTensor outputTensor;
            if (1 == inputData.currentRefCount() && 1 == inputTensor.currentRefCount()) {
                outputTensor = inputTensor;
                outputTensor.addRef();
            } else {
                @Nonnull final CudaDevice.CudaTensorDescriptor outputDescriptor = gpu.newTensorDescriptor(precision, length, inputSize[2], inputSize[1], inputSize[0], inputSize[2] * inputSize[1] * inputSize[0], inputSize[1] * inputSize[0], inputSize[0], 1);
                @Nonnull final CudaMemory outputData = gpu.allocate(precision.size * 1l * inputDims * length, MemoryType.Managed.normalize(), true);
                outputTensor = CudaTensor.wrap(outputData, outputDescriptor, precision);
            }
            try {
                CudaMemory inputMemory = inputTensor.getMemory(gpu);
                CudaMemory outputMemory = outputTensor.getMemory(gpu);
                CudaSystem.handle(gpu.cudnnSoftmaxForward(algorithm.code, mode.code, precision.getPointer(1.0), inputTensor.descriptor.getPtr(), inputMemory.getPtr(), precision.getPointer(0.0), outputTensor.descriptor.getPtr(), outputMemory.getPtr()));
                assert CudaDevice.isThreadDeviceId(gpu.getDeviceId());
                inputMemory.dirty();
                outputMemory.dirty();
                outputMemory.freeRef();
                inputMemory.freeRef();
                return outputTensor;
            } catch (@Nonnull final Throwable e) {
                throw new ComponentException("Error apply " + Arrays.toString(inputSize), e);
            } finally {
                inputTensor.freeRef();
            }
        }, inputData);
        return new Result(CudaTensorList.create(outPtr, length, outputSize, precision), (@Nonnull final DeltaSet<Layer> buffer, @Nonnull final TensorList delta) -> {
            if (inputResult.isAlive()) {
                final TensorList data = CudaSystem.run(gpu -> {
                    @Nullable CudaTensor inputTensor;
                    synchronized (gpu) {
                        inputTensor = gpu.getTensor(inputData, precision, MemoryType.Device, true);
                    }
                    @Nullable CudaTensor deltaTensor;
                    synchronized (gpu) {
                        deltaTensor = gpu.getTensor(delta, precision, MemoryType.Device, true);
                    }
                    outPtr.addRef();
                    CudaTensor localOut = outPtr.getDenseAndFree(gpu);
                    delta.freeRef();
                    CudaTensor passbackTensor;
                    passbackTensor = CudaTensor.wrap(gpu.allocate((long) Tensor.length(inputSize) * length * precision.size, MemoryType.Managed.normalize(), false), gpu.newTensorDescriptor(precision, delta.length(), inputSize[2], inputSize[1], inputSize[0], inputSize[2] * inputSize[1] * inputSize[0], inputSize[1] * inputSize[0], inputSize[0], 1), precision);
                    try {
                        CudaMemory localOutMemory = localOut.getMemory(gpu);
                        CudaMemory deltaTensorMemory = deltaTensor.getMemory(gpu);
                        CudaMemory inputMemory = inputTensor.getMemory(gpu);
                        CudaMemory passbackMemory = passbackTensor.getMemory(gpu);
                        CudaSystem.handle(gpu.cudnnSoftmaxBackward(algorithm.code, mode.code, precision.getPointer(1.0), localOut.descriptor.getPtr(), localOutMemory.getPtr(), deltaTensor.descriptor.getPtr(), deltaTensorMemory.getPtr(), precision.getPointer(0.0), passbackTensor.descriptor.getPtr(), passbackMemory.getPtr()));
                        localOutMemory.dirty();
                        deltaTensorMemory.dirty();
                        passbackMemory.dirty();
                        localOutMemory.freeRef();
                        deltaTensorMemory.freeRef();
                        inputMemory.freeRef();
                        passbackMemory.freeRef();
                    } catch (@Nonnull final Throwable e) {
                        throw new ComponentException("Error apply " + Arrays.toString(inputSize), e);
                    } finally {
                        localOut.freeRef();
                        inputTensor.freeRef();
                        deltaTensor.freeRef();
                    }
                    return CudaTensorList.wrap(passbackTensor, length, inputSize, precision);
                }, delta);
                inputResult.accumulate(buffer, data);
            } else {
                delta.freeRef();
            }
        }) {

            @Override
            public final void accumulate(DeltaSet<Layer> buffer, TensorList delta) {
                getAccumulator().accept(buffer, delta);
            }

            @Override
            protected void _free() {
                inputData.freeRef();
                outPtr.freeRef();
                inputResult.freeRef();
            }

            @Override
            public boolean isAlive() {
                return inputResult.isAlive() || !isFrozen();
            }
        };
    } catch (@Nonnull final Throwable e) {
        throw new ComponentException("Error apply image res " + Arrays.toString(inputSize), e);
    }
}
Also used : CudaTensor(com.simiacryptus.mindseye.lang.cudnn.CudaTensor) CudaDevice(com.simiacryptus.mindseye.lang.cudnn.CudaDevice) Nonnull(javax.annotation.Nonnull) CudaMemory(com.simiacryptus.mindseye.lang.cudnn.CudaMemory) DeltaSet(com.simiacryptus.mindseye.lang.DeltaSet) CudaTensorList(com.simiacryptus.mindseye.lang.cudnn.CudaTensorList) TensorList(com.simiacryptus.mindseye.lang.TensorList) Result(com.simiacryptus.mindseye.lang.Result) ComponentException(com.simiacryptus.mindseye.lang.ComponentException) Nullable(javax.annotation.Nullable) Nullable(javax.annotation.Nullable)

Aggregations

ComponentException (com.simiacryptus.mindseye.lang.ComponentException)7 Nullable (javax.annotation.Nullable)6 DeltaSet (com.simiacryptus.mindseye.lang.DeltaSet)4 Result (com.simiacryptus.mindseye.lang.Result)4 TensorList (com.simiacryptus.mindseye.lang.TensorList)4 CudaDevice (com.simiacryptus.mindseye.lang.cudnn.CudaDevice)4 CudaMemory (com.simiacryptus.mindseye.lang.cudnn.CudaMemory)4 CudaTensor (com.simiacryptus.mindseye.lang.cudnn.CudaTensor)4 CudaTensorList (com.simiacryptus.mindseye.lang.cudnn.CudaTensorList)4 Nonnull (javax.annotation.Nonnull)4 ReferenceCounting (com.simiacryptus.mindseye.lang.ReferenceCounting)2 JsonElement (com.google.gson.JsonElement)1 JsonObject (com.google.gson.JsonObject)1 Coordinate (com.simiacryptus.mindseye.lang.Coordinate)1 DataSerializer (com.simiacryptus.mindseye.lang.DataSerializer)1 Layer (com.simiacryptus.mindseye.lang.Layer)1 LayerBase (com.simiacryptus.mindseye.lang.LayerBase)1 Tensor (com.simiacryptus.mindseye.lang.Tensor)1 CudaResource (com.simiacryptus.mindseye.lang.cudnn.CudaResource)1 CudaSettings (com.simiacryptus.mindseye.lang.cudnn.CudaSettings)1