public PooledObject <CudaBlas> BlasForTensor(Tensor tensor) { return(BlasForDevice(CudaHelpers.GetDeviceId(tensor))); }
public CudaContext CudaContextForTensor(Tensor tensor) { return(CudaContextForDevice(CudaHelpers.GetDeviceId(tensor))); }
//TODO this is not actually used at the moment. It probably should be. // excludeDim may be -1 to not exclude any dimension /// <summary> /// Collapses the dims. /// </summary> /// <param name="tensor">The tensor.</param> /// <param name="excludeDim">The exclude dim.</param> /// <param name="info">The information.</param> /// <returns>System.Int32.</returns> /// <exception cref="ArgumentException">excludeDim must equal -1 if all dims are of size 1 - excludeDim</exception> public static int CollapseDims(Tensor tensor, int excludeDim, out TensorInfo info) { info.buffer = CudaHelpers.GetBufferStart(tensor); var firstNonOneDim = GetInnermostNon1Dim(tensor.Shape, excludeDim); // If all dims are size 1 (ie. tensor contains 1 element) if (firstNonOneDim == -1) { if (excludeDim != -1) { throw new ArgumentException("excludeDim must equal -1 if all dims are of size 1", "excludeDim"); } info.sizes = new long[] { 1 }; info.strides = new long[] { 1 }; return(0); } // Count the number of successive dimensions that can be collapsed, from // innermost to outermost. int numCollapsed = 0; // Skip the leading size 1 dims numCollapsed += tensor.DimensionCount - 1 - firstNonOneDim; // We perform one pass through to determine how many dimensions we // can collapse, before calculating the actual size of the collapsed // dimensions. // size/strideInner are the size/strides of the previous inner // non-collapsible dim we encounter. var sizeInner = tensor.Shape[firstNonOneDim]; var strideInner = tensor.Strides[firstNonOneDim]; for (int i = firstNonOneDim - 1; i >= 0; --i) { var sizeOuter = tensor.Shape[i]; var strideOuter = tensor.Strides[i]; // Don't collapse this dimension if we want to exclude it from // collapsing. // Since this code is attempting to collapse a subsequent // dimension (i) with the preceding dimension (i + 1), we can only // perform collapsing if the preceding dimension can be collapsed // (i.e., not excludeDim) if ((excludeDim != i) && (excludeDim != i + 1)) { // The next outermost dimension can be skipped if size 1 if (sizeOuter == 1) { ++numCollapsed; continue; } // If the next outermost dimension is contiguous with the // previous non-collapsed one, collapse it if (strideOuter == strideInner * sizeInner) { ++numCollapsed; // This is the run of collapsed dimensions' size sizeInner = sizeInner * sizeOuter; continue; } } // Otherwise, this new outer dimension at `i` cannot be collapsed // because it is excluded from collapsing, or it is not contiguous // with the previous inner dimension. sizeInner = sizeOuter; strideInner = strideOuter; } // This will be our new size/stride and dimension. var newSizes = new long[TSCudaContext.MaxDims]; var newStrides = new long[TSCudaContext.MaxDims]; int newDims = tensor.DimensionCount - numCollapsed; // We return the index of the excluded dimension that is excluded // from being collapsed here. int returnDim = -1; // We perform a second pass through the dimensions to actually // calculate the size of the collapsed dimensions. int collapsedIndex = tensor.DimensionCount - numCollapsed - 1; newSizes[collapsedIndex] = tensor.Shape[firstNonOneDim]; newStrides[collapsedIndex] = tensor.Strides[firstNonOneDim]; if (firstNonOneDim == excludeDim) { returnDim = collapsedIndex; } for (int i = firstNonOneDim - 1; i >= 0; --i) { var sizeOuter = tensor.Shape[i]; var strideOuter = tensor.Strides[i]; if ((excludeDim != i) && (excludeDim != i + 1)) { if (sizeOuter == 1) { // skip continue; } if (strideOuter == newSizes[collapsedIndex] * newStrides[collapsedIndex]) { // collapse newSizes[collapsedIndex] *= sizeOuter; continue; } } // Otherwise, strides don't match, or dim `i` is excluded from // collapsing. --collapsedIndex; //assert(collapsedIndex >= 0); //assert(collapsedIndex < newDims); newSizes[collapsedIndex] = sizeOuter; newStrides[collapsedIndex] = strideOuter; if (excludeDim == i) { returnDim = collapsedIndex; } } info.sizes = newSizes.Take(newDims).ToArray(); info.strides = newStrides.Take(newDims).ToArray(); return(returnDim); }
public Tensor Addmm(Tensor result, float beta, Tensor src, float alpha, Tensor m1, Tensor m2) { try { TSCudaContext context = CudaHelpers.TSContextForTensor(src); if (src.ElementType != m1.ElementType || src.ElementType != m2.ElementType || (result != null && result.ElementType != src.ElementType)) { throw new InvalidOperationException("All tensors must have the same element type"); } if (result != null && !(result.Storage is CudaStorage)) { throw new ArgumentException("result must be a CUDA tensor", "result"); } if (!(m1.Storage is CudaStorage)) { throw new ArgumentException("m1 must be a CUDA tensor", "m1"); } if (!(m2.Storage is CudaStorage)) { throw new ArgumentException("m2 must be a CUDA tensor", "m2"); } if (src.DimensionCount != 2) { throw new ArgumentException("src must be a matrix", "src"); } if (m1.DimensionCount != 2) { throw new ArgumentException("m1 must be a matrix", "m1"); } if (m2.DimensionCount != 2) { throw new ArgumentException("m2 must be a matrix", "m2"); } if (src.Sizes[0] != m1.Sizes[0] || src.Sizes[1] != m2.Sizes[1] || m1.Sizes[1] != m2.Sizes[0]) { throw new InvalidOperationException($"Size mismatch, srcSize0 = {src.Sizes[0]}, m1Size0 = {m1.Sizes[0]}, srcSize1 = {src.Sizes[1]}, m2Size1 = {m2.Sizes[1]}, m1Size1 = '{m1.Sizes[1]}', m2Size0 = '{m2.Sizes[0]}'"); } Tensor writeTarget = TensorResultBuilder.GetWriteTarget(result, src, true, src.Sizes); if (writeTarget != src) { Ops.Copy(writeTarget, src); } CudaMatrixMulMM.Gemm(context, alpha, m1, m2, beta, writeTarget); return(writeTarget); } catch (Exception err) { Logger.WriteLine($"Exception in Addmm: '{err.Message}'"); Logger.WriteLine($"Call stack: '{err.StackTrace}'"); throw err; } }
private static CudaDeviceVariable <float> GetDeviceVar(Tensor tensor) { var ptr = CudaHelpers.GetBufferStart(tensor); return(new CudaDeviceVariable <float>(ptr, false, 0));// set size to 0 because we never end up using it }
/// <summary> /// DNNs for tensor. /// </summary> /// <param name="tensor">The tensor.</param> /// <returns>PooledObject<ManagedCuda.CudaDNN.CudaDNNContext>.</returns> public PooledObject <ManagedCuda.CudaDNN.CudaDNNContext> DNNForTensor(NDArray tensor) { var deviceId = CudaHelpers.GetDeviceId(tensor); return(devices[deviceId].DnnHandles.Get()); }