diff --git a/h2o-algos/src/main/java/hex/ContributionsWithBackgroundFrameTask.java b/h2o-algos/src/main/java/hex/ContributionsWithBackgroundFrameTask.java index f24ccaacbe89..e3626856fa0d 100644 --- a/h2o-algos/src/main/java/hex/ContributionsWithBackgroundFrameTask.java +++ b/h2o-algos/src/main/java/hex/ContributionsWithBackgroundFrameTask.java @@ -200,9 +200,8 @@ public Frame runAndGetOutput(Job j, Key destinationKey, String[] names) { Log.warn("Not enough memory to calculate SHAP at once. Calculating in " + (nSubFrames) + " iterations."); _isFrameBigger = false; // ensure we map over the BG frame so we can average over the results properly; - Frame result = null; - List subFrames = new LinkedList(); - try { + try (Scope.Safe safe = Scope.safe()) { + List subFrames = new LinkedList(); for (int i = 0; i < nSubFrames; i++) { setChunkRange(i * chunksPerIter, Math.min(nChunks - 1, (i + 1) * chunksPerIter - 1)); Frame indivContribs = clone().withPostMapAction(JobUpdatePostMap.forJob(j)) @@ -217,23 +216,14 @@ public Frame runAndGetOutput(Job j, Key destinationKey, String[] names) { indivContribs.delete(); } - result = concatFrames(subFrames, destinationKey); - Set homes = new HashSet<>(); + Frame result = concatFrames(subFrames, destinationKey); + Set homes = new HashSet<>(); // not used? for (int i = 0; i < result.anyVec().nChunks(); i++) { for (int k = 0; k < result.numCols(); k++) { homes.add(result.vec(k).chunkKey(i).home_node().getIpPortString()); } } - return result; - } finally { - if (null != result) { - for (Frame fr : subFrames) { - Frame.deleteTempFrameAndItsNonSharedVecs(fr, result); - } - } else { - for (Frame fr : subFrames) - fr.delete(); - } + return Scope.untrack(result); } } else { Frame indivContribs = withPostMapAction(JobUpdatePostMap.forJob(j)) diff --git a/h2o-algos/src/main/java/hex/deeplearning/DeepLearningModel.java b/h2o-algos/src/main/java/hex/deeplearning/DeepLearningModel.java index 5f54ea4be865..6d8292d3c7b7 100755 --- a/h2o-algos/src/main/java/hex/deeplearning/DeepLearningModel.java +++ b/h2o-algos/src/main/java/hex/deeplearning/DeepLearningModel.java @@ -46,13 +46,10 @@ public Frame scoreContributions(Frame frame, Key destination_key, Job tmpFrames = new LinkedList<>(); - Frame adaptedFrame = null; - Frame adaptedBgFrame = null; - try { - adaptedBgFrame = adaptFrameForScore(backgroundFrame, false, tmpFrames); + try (Scope.Safe s = Scope.safe(frame, backgroundFrame)) { + Frame adaptedBgFrame = adaptFrameForScore(backgroundFrame, false); DKV.put(adaptedBgFrame); - adaptedFrame = adaptFrameForScore(frame, false, tmpFrames); + Frame adaptedFrame = adaptFrameForScore(frame, false); DKV.put(adaptedFrame); DeepSHAPContributionsWithBackground contributions = new DeepSHAPContributionsWithBackground(this, adaptedFrame._key, @@ -70,10 +67,8 @@ public Frame scoreContributions(Frame frame, Key destination_key, Job destination_key, Job List baseModelsIdx = new ArrayList<>(); String[] columns = null; baseModelsIdx.add(0); - Frame fr = new Frame(); - Frame levelOneFrame = null; - Frame levelOneFrameBg = null; - Frame adaptFr = null; - Frame adaptFrBg = null; - try { + try (Scope.Safe s = Scope.safe(frame, backgroundFrame)) { + Frame fr = new Frame(); for (Key bm : _parms._base_models) { if (isUsefulBaseModel(bm)) { baseModels.add(bm.toString()); @@ -238,13 +234,11 @@ private Frame baseLineContributions(Frame frame, Key destination_key, Job String[] colsWithRows = columns; columns = Arrays.copyOfRange(columns, 0, columns.length - 3); - List tmpFrames = new ArrayList<>(); - adaptFr = adaptFrameForScore(frame, false, tmpFrames); - levelOneFrame = getLevelOnePredictFrame(frame, adaptFr, j); + Frame adaptFr = adaptFrameForScore(frame, false); + Frame levelOneFrame = getLevelOnePredictFrame(frame, adaptFr, j); - tmpFrames = new ArrayList<>(); - adaptFrBg = adaptFrameForScore(backgroundFrame, false, tmpFrames); - levelOneFrameBg = getLevelOnePredictFrame(backgroundFrame, adaptFrBg, j); + Frame adaptFrBg = adaptFrameForScore(backgroundFrame, false); + Frame levelOneFrameBg = getLevelOnePredictFrame(backgroundFrame, adaptFrBg, j); Frame metalearnerContrib = ((Model.Contributions) _output._metalearner).scoreContributions(levelOneFrame, Key.make(destination_key + "_" + _output._metalearner._key), j, @@ -258,22 +252,13 @@ private Frame baseLineContributions(Frame frame, Key destination_key, Job .map(name -> "metalearner_" + name) .toArray(String[]::new)); - fr.add(metalearnerContrib); - Frame.deleteTempFrameAndItsNonSharedVecs(metalearnerContrib, fr); - - - return new GDeepSHAP(columns, baseModels.toArray(new String[0]), + Scope.track(fr.add(metalearnerContrib)); + + return Scope.untrack(new GDeepSHAP(columns, baseModels.toArray(new String[0]), fr._names, baseModelsIdx.toArray(new Integer[0]), _parms._metalearner_transform) .withPostMapAction(JobUpdatePostMap.forJob(j)) .doAll(colsWithRows.length, Vec.T_NUM, fr) - .outputFrame(destination_key, colsWithRows, null); - - } finally { - if (null != levelOneFrame) Frame.deleteTempFrameAndItsNonSharedVecs(levelOneFrame, frame); - if (null != levelOneFrameBg) Frame.deleteTempFrameAndItsNonSharedVecs(levelOneFrameBg, backgroundFrame); - Frame.deleteTempFrameAndItsNonSharedVecs(fr, frame); - if (null != adaptFr) Frame.deleteTempFrameAndItsNonSharedVecs(adaptFr, frame); - if (null != adaptFrBg) Frame.deleteTempFrameAndItsNonSharedVecs(adaptFrBg, backgroundFrame); + .outputFrame(destination_key, colsWithRows, null)); } } @@ -487,36 +472,37 @@ public int nfeatures() { */ @Override protected PredictScoreResult predictScoreImpl(Frame fr, Frame adaptFrm, String destination_key, Job j, boolean computeMetrics, CFuncRef customMetricFunc) { - Frame levelOneFrame = getLevelOnePredictFrame(fr, adaptFrm, j); - // TODO: what if we're running multiple in parallel and have a name collision? - Log.info("Finished creating \"level one\" frame for scoring: " + levelOneFrame.toString()); - - // Score the dataset, building the class distribution & predictions - - Model metalearner = this._output._metalearner; - Frame predictFr = metalearner.score( - levelOneFrame, - destination_key, - j, - computeMetrics, - CFuncRef.from(_parms._custom_metric_func) - ); - ModelMetrics mmStackedEnsemble = null; - if (computeMetrics) { - // #score has just stored a ModelMetrics object for the (metalearner, preds_levelone) Model/Frame pair. - // We need to be able to look it up by the (this, fr) pair. - // The ModelMetrics object for the metalearner will be removed when the metalearner is removed. - Key[] mms = metalearner._output.getModelMetrics(); - ModelMetrics lastComputedMetric = mms[mms.length - 1].get(); - mmStackedEnsemble = lastComputedMetric.deepCloneWithDifferentModelAndFrame(this, fr); - this.addModelMetrics(mmStackedEnsemble); - //now that we have the metric set on the SE model, removing the one we just computed on metalearner (otherwise it leaks in client mode) - for (Key mm : metalearner._output.clearModelMetrics(true)) { - DKV.remove(mm); + try (Scope.Safe safe = Scope.safe(fr, adaptFrm)) { + Frame levelOneFrame = getLevelOnePredictFrame(fr, adaptFrm, j); + // TODO: what if we're running multiple in parallel and have a name collision? + Log.info("Finished creating \"level one\" frame for scoring: "+levelOneFrame.toString()); + + // Score the dataset, building the class distribution & predictions + + Model metalearner = this._output._metalearner; + Frame predictFr = metalearner.score( + levelOneFrame, + destination_key, + j, + computeMetrics, + CFuncRef.from(_parms._custom_metric_func) + ); + ModelMetrics mmStackedEnsemble = null; + if (computeMetrics) { + // #score has just stored a ModelMetrics object for the (metalearner, preds_levelone) Model/Frame pair. + // We need to be able to look it up by the (this, fr) pair. + // The ModelMetrics object for the metalearner will be removed when the metalearner is removed. + Key[] mms = metalearner._output.getModelMetrics(); + ModelMetrics lastComputedMetric = mms[mms.length-1].get(); + mmStackedEnsemble = lastComputedMetric.deepCloneWithDifferentModelAndFrame(this, fr); + this.addModelMetrics(mmStackedEnsemble); + //now that we have the metric set on the SE model, removing the one we just computed on metalearner (otherwise it leaks in client mode) + for (Key mm : metalearner._output.clearModelMetrics(true)) { + DKV.remove(mm); + } } + return new StackedEnsemblePredictScoreResult(predictFr, mmStackedEnsemble); } - Frame.deleteTempFrameAndItsNonSharedVecs(levelOneFrame, adaptFrm); - return new StackedEnsemblePredictScoreResult(predictFr, mmStackedEnsemble); } private Frame getLevelOnePredictFrame(Frame fr, Frame adaptFrm, Job j) { diff --git a/h2o-algos/src/main/java/hex/glm/GLMModel.java b/h2o-algos/src/main/java/hex/glm/GLMModel.java index 95eed2c80436..2b5eb656ef83 100755 --- a/h2o-algos/src/main/java/hex/glm/GLMModel.java +++ b/h2o-algos/src/main/java/hex/glm/GLMModel.java @@ -243,15 +243,12 @@ public Frame scoreContributions(Frame frame, Key destination_key, Job tmpFrames = new ArrayList<>(); - Frame adaptedFrame = null; - Frame adaptedBgFrame = null; if (null == backgroundFrame) throw H2O.unimpl("GLM supports contribution calculation only with a background frame."); Log.info("Starting contributions calculation for " + this._key + "..."); - try { - adaptedBgFrame = adaptFrameForScore(backgroundFrame, false, tmpFrames); - adaptedFrame = adaptFrameForScore(frame, false, tmpFrames); + try (Scope.Safe s = Scope.safe(frame, backgroundFrame)) { + Frame adaptedBgFrame = adaptFrameForScore(backgroundFrame, false); + Frame adaptedFrame = adaptFrameForScore(frame, false); DKV.put(adaptedBgFrame); DKV.put(adaptedFrame); DataInfo dinfo = _output._dinfo.clone(); @@ -277,13 +274,10 @@ public Frame scoreContributions(Frame frame, Key destination_key, Job destination_key, Job destination_key, Job destination_key, Job fun, Key destinationKey) { - LinkedList resultSubFrames = new LinkedList<>(); - Frame result = null; - try { + try (Scope.Safe safe = Scope.safe(frameToSplit)) { + List resultSubFrames = new LinkedList<>(); int nChunks = frameToSplit.anyVec().nChunks(); for (int cidx = 0; cidx < nChunks; cidx++) { Frame subFrame = createSubFrame(frameToSplit, cidx, destinationKey.toString()); - try { - if (subFrame.numRows() == 0) continue; - DKV.put(subFrame); - resultSubFrames.add(fun.apply(subFrame)); - } finally { - for (Vec v : subFrame.vecs()) - DKV.remove(v._key); - subFrame.delete(); - } - } - result = concatFrames(resultSubFrames, destinationKey); - return result; - } finally { - if (null != result) { - for (Frame fr : resultSubFrames) - Frame.deleteTempFrameAndItsNonSharedVecs(fr, frameToSplit); - } else { - for (Frame fr : resultSubFrames) - fr.delete(); + if (subFrame.numRows() == 0) continue; + DKV.put(subFrame); + resultSubFrames.add(Scope.track(fun.apply(subFrame))); } + return Scope.untrack(concatFrames(resultSubFrames, destinationKey)); } } } diff --git a/h2o-extensions/target-encoder/src/main/java/ai/h2o/targetencoding/TargetEncoderModel.java b/h2o-extensions/target-encoder/src/main/java/ai/h2o/targetencoding/TargetEncoderModel.java index b15759676a3f..6307d32693bd 100644 --- a/h2o-extensions/target-encoder/src/main/java/ai/h2o/targetencoding/TargetEncoderModel.java +++ b/h2o-extensions/target-encoder/src/main/java/ai/h2o/targetencoding/TargetEncoderModel.java @@ -226,20 +226,16 @@ public Frame transform(Frame fr, BlendingParams blendingParams, double noiseLeve */ public Frame transform(Frame fr, boolean asTraining, int outOfFold, BlendingParams blendingParams, double noiseLevel) { if (!canApplyTargetEncoding(fr)) return fr; - Frame adaptFr = null; - try { - adaptFr = adaptForEncoding(fr); - return applyTargetEncoding( + try (Scope.Safe safe = Scope.safe(fr)) { + Frame adaptFr = adaptForEncoding(fr); + return Scope.untrack(applyTargetEncoding( adaptFr, asTraining, outOfFold, blendingParams, noiseLevel, null - ); - } finally { - if (adaptFr != null) - Frame.deleteTempFrameAndItsNonSharedVecs(adaptFr, fr); + )); } } @@ -258,20 +254,16 @@ public Frame score(Frame fr, String destination_key, Job j, boolean computeMetri DKV.put(res); return res; } - Frame adaptFr = null; - try { - adaptFr = adaptForEncoding(fr); - return applyTargetEncoding( + try (Scope.Safe safe = Scope.safe(fr)) { + Frame adaptFr = adaptForEncoding(fr); + return Scope.untrack(applyTargetEncoding( adaptFr, false, NO_FOLD, _parms.getBlendingParameters(), _parms._noise, Key.make(destination_key) - ); - } finally { - if (adaptFr != null) - Frame.deleteTempFrameAndItsNonSharedVecs(adaptFr, fr); + )); } } diff --git a/h2o-extensions/xgboost/src/main/java/hex/tree/xgboost/XGBoostModel.java b/h2o-extensions/xgboost/src/main/java/hex/tree/xgboost/XGBoostModel.java index 72e2b961ea40..8bc7340558a1 100755 --- a/h2o-extensions/xgboost/src/main/java/hex/tree/xgboost/XGBoostModel.java +++ b/h2o-extensions/xgboost/src/main/java/hex/tree/xgboost/XGBoostModel.java @@ -716,15 +716,13 @@ public Frame scoreContributions(Frame frame, Key destination_key, Job destination_key, Job j, ContributionsOptions options, Frame backgroundFrame) { Log.info("Starting contributions calculation for " + this._key + "..."); - Frame adaptedFrame = null; - Frame adaptedBgFrame = null; - try { + try (Scope.Safe s = Scope.safe(frame, backgroundFrame)) { if (null == backgroundFrame) return scoreContributions(frame, destination_key, j, options); - adaptedFrame = new Frame(frame); + Frame adaptedFrame = new Frame(frame); adaptTestForTrain(adaptedFrame, true, false); DKV.put(adaptedFrame); - adaptedBgFrame = new Frame(backgroundFrame); + Frame adaptedBgFrame = new Frame(backgroundFrame); adaptTestForTrain(adaptedBgFrame, true, false); DKV.put(adaptedBgFrame); @@ -735,12 +733,10 @@ public Frame scoreContributions(Frame frame, Key destination_key, Job