From f580d5a3abd3f7b03a7e9031c4c92316fed4555d Mon Sep 17 00:00:00 2001 From: Leon Chen Date: Tue, 25 Oct 2016 10:52:09 -0400 Subject: [PATCH] additional fallback to CPU when tensor MAX_TEXTURE_SIZE exceeded (#8) --- src/layers/convolutional/Convolution3D.js | 2 +- src/layers/convolutional/Deconvolution2D.js | 2 +- .../convolutional/SeparableConvolution2D.js | 45 +++---------------- src/layers/core/Dense.js | 3 ++ 4 files changed, 10 insertions(+), 42 deletions(-) diff --git a/src/layers/convolutional/Convolution3D.js b/src/layers/convolutional/Convolution3D.js index 4b195f3..bb94c57 100644 --- a/src/layers/convolutional/Convolution3D.js +++ b/src/layers/convolutional/Convolution3D.js @@ -248,7 +248,7 @@ export default class Convolution3D extends Layer { const nbPatches = outputDim1 * outputDim2 * outputDim3 const matMul = new Tensor([], [nbPatches, nbFilter]) - if (this._useWeblas) { + if (this._useWeblas && !(this._volColsMat._gpuMaxSizeExceeded || this._wRowsMat._gpuMaxSizeExceeded)) { const bias = this.bias ? this.weights.b.weblasTensor : this._zerosVec.weblasTensor matMul.tensor.data = weblas.pipeline.sgemm( 1, this._volColsMat.weblasTensor, this._wRowsMat.weblasTensor, diff --git a/src/layers/convolutional/Deconvolution2D.js b/src/layers/convolutional/Deconvolution2D.js index cc359ea..5244a25 100644 --- a/src/layers/convolutional/Deconvolution2D.js +++ b/src/layers/convolutional/Deconvolution2D.js @@ -185,7 +185,7 @@ export default class Deconvolution2D extends Layer { const [nbFilter, nbRow, nbCol] = this.kernelShape const matMul = new Tensor([], [inputRows * inputCols, nbRow * nbCol * nbFilter]) - if (this._useWeblas) { + if (this._useWeblas && !(imColsMat._gpuMaxSizeExceeded || this._wRowsMat._gpuMaxSizeExceeded)) { let _zerosVec = new Tensor([], [this.weights.W.tensor.shape[3]]) _zerosVec.createWeblasTensor() matMul.tensor.data = weblas.pipeline.sgemm( diff --git a/src/layers/convolutional/SeparableConvolution2D.js b/src/layers/convolutional/SeparableConvolution2D.js index a62f05b..d49ef97 100644 --- a/src/layers/convolutional/SeparableConvolution2D.js +++ b/src/layers/convolutional/SeparableConvolution2D.js @@ -81,58 +81,28 @@ class _DepthwiseConvolution2D extends Convolution2D { * @returns {Tensor} x */ call (x) { - let startTime = performance.now() this._calcOutputShape(x) - let endTime = performance.now() - console.log(0, endTime - startTime) - startTime = performance.now() this._padInput(x) - endTime = performance.now() - console.log(1, endTime - startTime) - startTime = performance.now() this._im2col(x) - endTime = performance.now() - console.log(2, endTime - startTime) - startTime = performance.now() const nbFilter = this.kernelShape[0] const outputRows = this.outputShape[0] const outputCols = this.outputShape[1] const nbPatches = outputRows * outputCols const matMul = new Tensor([], [nbPatches * x.tensor.shape[2], nbFilter * x.tensor.shape[2]]) - endTime = performance.now() - console.log(3, endTime - startTime) - startTime = performance.now() - if (this._useWeblas) { + if (this._useWeblas && !(this._imColsMat._gpuMaxSizeExceeded || this._wRowsMat._gpuMaxSizeExceeded)) { // GPU - if (this._imColsMat.weblasTensorsSplit) { - // split matrix multiply if this._imColsMat dimension > webgl.MAX_TEXTURE_SIZE - let offset = 0 - this._imColsMat.weblasTensorsSplit.forEach(imColsMatSplit => { - const matMulSplitData = weblas.pipeline.sgemm( - 1, imColsMatSplit, this._wRowsMat.weblasTensor, - 1, this._zerosVec.weblasTensor - ).transfer() - matMul.tensor.data.set(matMulSplitData, offset) - offset += matMulSplitData.length - }) - } else { - // normal matrix multiply - matMul.tensor.data = weblas.pipeline.sgemm( - 1, this._imColsMat.weblasTensor, this._wRowsMat.weblasTensor, - 1, this._zerosVec.weblasTensor - ).transfer() - } + matMul.tensor.data = weblas.pipeline.sgemm( + 1, this._imColsMat.weblasTensor, this._wRowsMat.weblasTensor, + 1, this._zerosVec.weblasTensor + ).transfer() } else { // CPU gemm(matMul.tensor, this._imColsMat.tensor, this._wRowsMat.tensor, 1, 1) } - endTime = performance.now() - console.log(4, endTime - startTime) - startTime = performance.now() let output = new Tensor([], [outputRows, outputCols, x.tensor.shape[2] * nbFilter]) const outputDataLength = outputRows * outputCols * x.tensor.shape[2] * nbFilter let dataFiltered = new Float32Array(outputDataLength) @@ -144,8 +114,6 @@ class _DepthwiseConvolution2D extends Convolution2D { } } output.replaceTensorData(dataFiltered) - endTime = performance.now() - console.log(5, endTime - startTime) x.tensor = output.tensor @@ -233,10 +201,7 @@ export default class SeparableConvolution2D extends Layer { const depthwiseOutput = this._depthwiseConv.call(x) // Perform depthwise ops - let startTime = performance.now() const pointwiseOutput = this._pointwiseConv.call(depthwiseOutput) - let endTime = performance.now() - console.log(6, endTime - startTime) x.tensor = pointwiseOutput.tensor diff --git a/src/layers/core/Dense.js b/src/layers/core/Dense.js index 57a0565..4818660 100644 --- a/src/layers/core/Dense.js +++ b/src/layers/core/Dense.js @@ -77,6 +77,9 @@ export default class Dense extends Layer { if (this._useWeblas) { x.createWeblasTensor() + } + + if (this._useWeblas && !(x._gpuMaxSizeExceeded || this.weights.W._gpuMaxSizeExceeded)) { const bias = this.bias ? this.weights.b.weblasTensor : this._zerosVec.weblasTensor y.tensor.data = weblas.pipeline.sgemm( 1, x.weblasTensor, this.weights.W.weblasTensor,