Skip to content
This repository has been archived by the owner on Nov 17, 2023. It is now read-only.

Commit

Permalink
Deprecate NDArrayCollector and instead use ResourceScope (#14780)
Browse files Browse the repository at this point in the history
  • Loading branch information
zachgk authored and lanking520 committed May 11, 2019
1 parent f4598e7 commit 4796851
Show file tree
Hide file tree
Showing 21 changed files with 72 additions and 60 deletions.
14 changes: 10 additions & 4 deletions scala-package/core/src/main/scala/org/apache/mxnet/NDArray.scala
Original file line number Diff line number Diff line change
Expand Up @@ -741,10 +741,16 @@ object NDArray extends NDArrayBase {
* </b>
*/
class NDArray private[mxnet](private[mxnet] val handle: NDArrayHandle,
val writable: Boolean = true,
addToCollector: Boolean = true) extends NativeResource {
if (addToCollector) {
NDArrayCollector.collect(this)
val writable: Boolean) extends NativeResource {

@deprecated("Please use ResourceScope instead", "1.5.0")
def this(handle: NDArrayHandle,
writable: Boolean = true,
addToCollector: Boolean = true) {
this(handle, writable)
if (addToCollector) {
NDArrayCollector.collect(this)
}
}

override def nativeAddress: CPtrAddress = handle
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ import scala.collection.mutable
* });
* </pre>
*/
@deprecated("Please use ResourceScope instead", "1.5.0")
object NDArrayCollector {
private val logger = LoggerFactory.getLogger(classOf[NDArrayCollector])

Expand All @@ -75,24 +76,28 @@ object NDArrayCollector {
* Create a collector which will dispose the collected NDArrays automatically.
* @return an auto-disposable collector.
*/
@deprecated("Please use ResourceScope instead", "1.5.0")
def auto(): NDArrayCollector = new NDArrayCollector(true)

/**
* Create a collector allows users to later dispose the collected NDArray manually.
* @return a manually-disposable collector.
*/
@deprecated("Please use ResourceScope instead", "1.5.0")
@Experimental
def manual(): NDArrayCollector = new NDArrayCollector(false)

/**
* Collect the NDArrays into the collector of the current thread.
* @param ndArray NDArrays need to be collected.
*/
@deprecated("Please use ResourceScope instead", "1.5.0")
@varargs def collect(ndArray: NDArray*): Unit = {
currCollector.get().add(ndArray: _*)
}
}

@deprecated("Please use ResourceScope instead", "1.5.0")
class NDArrayCollector private(private val autoDispose: Boolean = true,
private val doCollect: Boolean = true) {
// native ptr (handle) of the NDArray -> NDArray
Expand Down Expand Up @@ -142,6 +147,7 @@ class NDArrayCollector private(private val autoDispose: Boolean = true,
* @return The result of function <em>codeBlock</em>.
*/
@Experimental
@deprecated("Please use ResourceScope instead", "1.5.0")
def withScope[T](codeBlock: => T): T = {
val old = NDArrayCollector.currCollector.get()
NDArrayCollector.currCollector.set(this)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,14 @@ class ResourceScope extends AutoCloseable {
resource.scope = Some(this)
}

/**
* Check if a NativeResource is in the scope
* @param resource
*/
def contains(resource: NativeResource): Boolean = {
resourceQ.contains(resource)
}

/**
* Remove NativeResource from the Scope, this uses
* object equality to find the resource in the stack.
Expand All @@ -80,8 +88,10 @@ class ResourceScope extends AutoCloseable {
def moveToOuterScope(resource: NativeResource): Unit = {
val prevScope: Option[ResourceScope] = ResourceScope.getPrevScope()
if (prevScope.isDefined) {
this.remove(resource)
prevScope.get.add(resource)
if (contains(resource)) {
this.remove(resource)
prevScope.get.add(resource)
}
} else this.remove(resource)
}

Expand Down Expand Up @@ -109,20 +119,16 @@ object ResourceScope {

val curScope = if (scope != null) scope else new ResourceScope()

@inline def resourceInGeneric(g: scala.collection.Iterable[_]) = {
g.foreach( n =>
n match {
case nRes: NativeResource => {
curScope.moveToOuterScope(nRes)
}
case kv: scala.Tuple2[_, _] => {
if (kv._1.isInstanceOf[NativeResource]) curScope.moveToOuterScope(
kv._1.asInstanceOf[NativeResource])
if (kv._2.isInstanceOf[NativeResource]) curScope.moveToOuterScope(
kv._2.asInstanceOf[NativeResource])
}
}
)
def recursiveMoveToOuterScope(resource: Any): Unit = {
resource match {
case nRes: NativeResource => curScope.moveToOuterScope(nRes)
case ndRet: NDArrayFuncReturn => ndRet.arr.foreach( nd => curScope.moveToOuterScope(nd) )
case resInGeneric: scala.collection.Traversable[_] =>
resInGeneric.foreach(recursiveMoveToOuterScope)
case resProduct: scala.Product =>
resProduct.productIterator.foreach(recursiveMoveToOuterScope)
case _ => // do nothing
}
}

@inline def safeAddSuppressed(t: Throwable, suppressed: Throwable): Unit = {
Expand All @@ -133,13 +139,7 @@ object ResourceScope {

try {
val ret = body
ret match {
// don't de-allocate if returning any collection that contains NativeResource.
case resInGeneric: scala.collection.Iterable[_] => resourceInGeneric(resInGeneric)
case nRes: NativeResource => curScope.moveToOuterScope(nRes)
case ndRet: NDArrayFuncReturn => ndRet.arr.foreach( nd => curScope.moveToOuterScope(nd) )
case _ => // do nothing
}
recursiveMoveToOuterScope(ret)
ret
} catch {
case t: Throwable =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ class NDArrayIter(data: IndexedSeq[(DataDesc, NDArray)],
val shape = Shape(dataBatchSize) ++ ndArray.shape.slice(1, ndArray.shape.size)
// The new NDArray has to be created such that it inherits dtype from the passed in array
val newArray = NDArray.zeros(shape, dtype = ndArray.dtype)
NDArrayCollector.auto().withScope {
ResourceScope.using() {
val batch = ndArray.slice(cursor, numData)
val padding = ndArray.slice(0, padNum)
newArray.slice(0, dataBatchSize - padNum).set(batch)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ object ScalaInferenceBenchmark {
List[Long] = {
var inferenceTimes: List[Long] = List()
for (i <- 1 to totalRuns) {
NDArrayCollector.auto().withScope {
ResourceScope.using() {
val startTimeSingle = System.currentTimeMillis()
objectToRun.runSingleInference(loadedModel, dataSet)
val estimatedTimeSingle = System.currentTimeMillis() - startTimeSingle
Expand All @@ -67,7 +67,7 @@ object ScalaInferenceBenchmark {

var inferenceTimes: List[Long] = List()
for (batch <- dataSetBatches) {
NDArrayCollector.auto().withScope {
ResourceScope.using() {
val loadedBatch = objecToRun.loadInputBatch(batch)
val startTimeSingle = System.currentTimeMillis()
objecToRun.runBatchInference(loadedModel, loadedBatch)
Expand Down Expand Up @@ -133,7 +133,7 @@ object ScalaInferenceBenchmark {

logger.info("Running single inference call")
// Benchmarking single inference call
NDArrayCollector.auto().withScope {
ResourceScope.using() {
val loadedModel = loadModel(exampleToBenchmark, context, false)
val dataSet = loadDataSet(exampleToBenchmark)
val inferenceTimes = runInference(exampleToBenchmark, loadedModel, dataSet, baseCLI.count)
Expand All @@ -143,7 +143,7 @@ object ScalaInferenceBenchmark {
if (baseCLI.batchSize != 0) {
logger.info("Running for batch inference call")
// Benchmarking batch inference call
NDArrayCollector.auto().withScope {
ResourceScope.using() {
val loadedModel = loadModel(exampleToBenchmark, context, true)
val batchDataSet = loadBatchDataSet(exampleToBenchmark, baseCLI.batchSize)
val inferenceTimes = runBatchInference(exampleToBenchmark, loadedModel, batchDataSet)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
package org.apache.mxnetexamples.cnntextclassification

import org.apache.mxnet.optimizer.RMSProp
import org.apache.mxnet.{Context, Executor, Model, NDArray, NDArrayCollector, Optimizer, Shape, Symbol, Uniform}
import org.apache.mxnet.{Context, Executor, Model, NDArray, Optimizer, ResourceScope, Shape, Symbol, Uniform}
import org.kohsuke.args4j.{CmdLineParser, Option}
import org.slf4j.LoggerFactory

Expand Down Expand Up @@ -131,7 +131,7 @@ object CNNTextClassification {
numTotal = 0f
updateRate = 0

NDArrayCollector.auto().withScope {
ResourceScope.using() {
for (begin <- 0 until trainBatches.length by batchSize) {
val (batchD, batchL) = {
if (begin + batchSize <= trainBatches.length) {
Expand Down Expand Up @@ -239,7 +239,7 @@ object CNNTextClassification {

def test(w2vFilePath : String, mrDatasetPath: String,
ctx : Context, saveModelPath: String) : Float = {
val output = NDArrayCollector.auto().withScope {
val output = ResourceScope.using() {
val (numEmbed, word2vec) = DataHelper.loadGoogleModel(w2vFilePath)
val (datas, labels) = DataHelper.loadMSDataWithWord2vec(
mrDatasetPath, numEmbed, word2vec)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ package org.apache.mxnetexamples.customop

import org.apache.mxnet.Callback.Speedometer
import org.apache.mxnet.DType.DType
import org.apache.mxnet.{Accuracy, Context, CustomOp, CustomOpProp, NDArray, NDArrayCollector, Operator, Shape, Symbol, Xavier}
import org.apache.mxnet.{Accuracy, Context, CustomOp, CustomOpProp, NDArray, Operator, ResourceScope, Shape, Symbol, Xavier}
import org.apache.mxnet.optimizer.RMSProp
import org.kohsuke.args4j.{CmdLineParser, Option}
import org.slf4j.LoggerFactory
Expand Down Expand Up @@ -141,7 +141,7 @@ object ExampleCustomOp {
evalMetric.reset()
var nBatch = 0
var epochDone = false
NDArrayCollector.auto().withScope {
ResourceScope.using() {
trainIter.reset()
while (!epochDone) {
var doReset = true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@

package org.apache.mxnetexamples.gan

import org.apache.mxnet.{Context, CustomMetric, DataBatch, IO, NDArray, NDArrayCollector, Shape, Symbol, Xavier}
import org.apache.mxnet.{Context, CustomMetric, DataBatch, IO, NDArray, ResourceScope, Shape, Symbol, Xavier}
import org.apache.mxnet.optimizer.Adam
import org.kohsuke.args4j.{CmdLineParser, Option}
import org.slf4j.LoggerFactory
Expand Down Expand Up @@ -104,7 +104,7 @@ object GanMnist {

def runTraining(dataPath : String, context : Context,
outputPath : String, numEpoch : Int): Float = {
val output = NDArrayCollector.auto().withScope {
val output = ResourceScope.using() {
val lr = 0.0005f
val beta1 = 0.5f
val batchSize = 100
Expand Down Expand Up @@ -147,7 +147,7 @@ object GanMnist {
t = 0
while (mnistIter.hasNext) {
dataBatch = mnistIter.next()
NDArrayCollector.auto().withScope {
ResourceScope.using() {
gMod.update(dataBatch)
gMod.dLabel.set(0f)
metricAcc.update(Array(gMod.dLabel), gMod.outputsFake)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ object ImageClassifierExample {
def runInferenceOnSingleImage(modelPathPrefix: String, inputImagePath: String,
context: Array[Context]):
IndexedSeq[IndexedSeq[(String, Float)]] = {
NDArrayCollector.auto().withScope {
ResourceScope.using() {
val dType = DType.Float32
val inputShape = Shape(1, 3, 224, 224)

Expand All @@ -71,7 +71,7 @@ object ImageClassifierExample {
def runInferenceOnBatchOfImage(modelPathPrefix: String, inputImageDir: String,
context: Array[Context]):
IndexedSeq[IndexedSeq[(String, Float)]] = {
NDArrayCollector.auto().withScope {
ResourceScope.using() {
val dType = DType.Float32
val inputShape = Shape(1, 3, 224, 224)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ object SSDClassifierExample {
def runObjectDetectionSingle(modelPathPrefix: String, inputImagePath: String,
context: Array[Context]):
IndexedSeq[IndexedSeq[(String, Array[Float])]] = {
NDArrayCollector.auto().withScope {
ResourceScope.using() {
val dType = DType.Float32
val inputShape = Shape(1, 3, 512, 512)
// ssd detections, numpy.array([[id, score, x1, y1, x2, y2]...])
Expand All @@ -68,7 +68,7 @@ object SSDClassifierExample {
def runObjectDetectionBatch(modelPathPrefix: String, inputImageDir: String,
context: Array[Context]):
IndexedSeq[IndexedSeq[(String, Array[Float])]] = {
NDArrayCollector.auto().withScope {
ResourceScope.using() {
val dType = DType.Float32
val inputShape = Shape(1, 3, 512, 512)
// ssd detections, numpy.array([[id, score, x1, y1, x2, y2]...])
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import org.slf4j.LoggerFactory

import scala.collection.JavaConverters._
import org.apache.commons.io.FileUtils
import org.apache.mxnet.{Context, DataBatch, DataDesc, DataIter, EvalMetric, Executor, NDArray, NDArrayCollector, Shape, Symbol, Xavier}
import org.apache.mxnet.{Context, DataBatch, DataDesc, DataIter, EvalMetric, Executor, NDArray, ResourceScope, Shape, Symbol, Xavier}
import org.apache.mxnet.DType.DType
import org.apache.mxnet.optimizer.RMSProp
import org.apache.mxnetexamples.Util
Expand Down Expand Up @@ -222,7 +222,7 @@ object ExampleMultiTask {

def train(batchSize: Int, numEpoch: Int, ctx: Context, modelDirPath: String):
(Executor, MultiAccuracy) = {
NDArrayCollector.auto().withScope {
ResourceScope.using() {
val lr = 0.001f
val network = ExampleMultiTask.buildNetwork()
val (trainIter, valIter) =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ object NeuralStyle {
contentWeight : Float, tvWeight : Float, gaussianRadius : Int,
lr: Float, maxNumEpochs: Int, maxLongEdge: Int,
saveEpochs : Int, stopEps: Float) : Unit = {
NDArrayCollector.auto().withScope {
ResourceScope.using() {
val contentNp = preprocessContentImage(contentImage, maxLongEdge, dev)
val styleNp = preprocessStyleImage(styleImage, contentNp.shape, dev)
val size = (contentNp.shape(2), contentNp.shape(3))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@

package org.apache.mxnetexamples.neuralstyle.end2end

import org.apache.mxnet.{Context, NDArrayCollector, Shape}
import org.apache.mxnet.{Context, ResourceScope, Shape}
import org.kohsuke.args4j.{CmdLineParser, Option}
import org.slf4j.LoggerFactory

Expand All @@ -29,7 +29,7 @@ object BoostInference {

def runInference(modelPath: String, outputPath: String, guassianRadius : Int,
inputImage : String, ctx : Context): Unit = {
NDArrayCollector.auto().withScope {
ResourceScope.using() {
val dShape = Shape(1, 3, 480, 640)
val clipNorm = 1.0f * dShape.product
// generator
Expand All @@ -47,7 +47,7 @@ object BoostInference {
DataProcessing.preprocessContentImage(s"$inputImage", dShape, ctx)
var data = Array(contentNp)
for (i <- 0 until gens.length) {
NDArrayCollector.auto().withScope {
ResourceScope.using() {
gens(i).forward(data.takeRight(1))
val newImg = gens(i).getOutputs()(0)
data :+= newImg
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ package org.apache.mxnetexamples.neuralstyle.end2end

import java.io.File

import org.apache.mxnet.{Context, Executor, NDArray, NDArrayCollector, Shape, Symbol}
import org.apache.mxnet.{Context, Executor, NDArray, ResourceScope, Shape, Symbol}
import org.apache.mxnet.optimizer.SGD
import org.kohsuke.args4j.{CmdLineParser, Option}
import org.slf4j.LoggerFactory
Expand Down Expand Up @@ -56,7 +56,7 @@ object BoostTrain {

def runTraining(dataPath : String, vggModelPath: String, ctx : Context,
styleImage : String, saveModelPath : String) : Unit = {
NDArrayCollector.auto().withScope {
ResourceScope.using() {
// params
val vggParams = NDArray.load2Map(vggModelPath)
val styleWeight = 1.2f
Expand Down Expand Up @@ -117,7 +117,7 @@ object BoostTrain {

// train
for (i <- startEpoch until endEpoch) {
NDArrayCollector.auto().withScope {
ResourceScope.using() {
filelist = Random.shuffle(filelist)
for (idx <- filelist.indices) {
var dataArray = Array[NDArray]()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ object LstmBucketing {

def runTraining(trainData : String, validationData : String,
ctx : Array[Context], numEpoch : Int): Unit = {
NDArrayCollector.auto().withScope {
ResourceScope.using() {
val batchSize = 32
val buckets = Array(10, 20, 30, 40, 50, 60)
val numHidden = 200
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ object TestCharRnn {
private val logger = LoggerFactory.getLogger(classOf[TrainCharRnn])

def runInferenceCharRNN(dataPath: String, modelPrefix: String, starterSentence : String): Unit = {
NDArrayCollector.auto().withScope {
ResourceScope.using() {
// The batch size for training
val batchSize = 32
// We can support various length input
Expand Down
Loading

0 comments on commit 4796851

Please sign in to comment.