c# tensorflow 記憶體洩露問題
阿新 • • 發佈:2018-12-18
記憶體洩露,造成原因有new完以後不釋放,程式碼放在迴圈中 ,new 大物件,記憶體很快耗光,舉個例子,乾淨的紙上用鉛筆亂畫東西,整個紙面畫完以後,就沒地方畫了,要想再畫的話,得用橡皮擦了。借別人的東西,老是不歸還,再借用的話,就不借給了。房間裡堆滿了東西,再往進放的話,就放不進去了。等等,生活中好多這樣的例子。看一下下面程式碼
using (MemoryStream ms = new MemoryStream()) { try { bmp.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg); } catch { return false; } var runner = session.GetRunner(); var tensor = CreateTensorFromImage(ms.GetBuffer()); runner.AddInput(graph["input"][0], tensor).Fetch(graph["output"][0]); var output = runner.Run(); var result = output[0]; var rshape = result.Shape; if (result.NumDims != 2 || rshape[0] != 1) { var shape = ""; foreach (var d in rshape) { // shape += $"{d} "; } shape = shape.Trim(); Environment.Exit(1); return false; } bool jagged = true; var bestIdx = 0; float best = 0; if (jagged) { var probabilities = ((float[][])result.GetValue(jagged: true))[0]; for (int i = 0; i < probabilities.Length; i++) { if (probabilities[i] > best) { bestIdx = i; best = probabilities[i]; } } } else { var val = (float[,])result.GetValue(jagged: false); for (int i = 0; i < val.GetLength(1); i++) { if (val[0, i] > best) { bestIdx = i; best = val[0, i]; } } } this.Invoke(new Action(() => { //nizh modify string tmpStr = labels[bestIdx]; if (tmpStr.IndexOf("sandship") != -1) { label1.Text = "XXXX_" + tmpStr; } else { label1.Text = tmpStr; } label1.Refresh(); } ) ); if (tensor != null) { tensor.Dispose(); tensor = null; } if (result != null) { result.Dispose(); result = null; } if (ms != null) { ms.Close(); ms.Dispose(); } if (bmp != null) { bmp.Dispose(); //bmp = null; } } GC.Collect(); GC.SuppressFinalize(this);
檢視帶有Dispose()的程式碼行,起初是沒有這些的,一起動程式,4個g記憶體很快就沒了。
GC.Collect();垃圾回收
var tensor = TFTensor.CreateString(contents); TFGraph graph; TFOutput input, output; // Construct a graph to normalize the image ConstructGraphToNormalizeImage(out graph, out input, out output); // Execute that graph to normalize this one image using (var session = new TFSession(graph)) { var normalized = session.Run( inputs: new[] { input }, inputValues: new[] { tensor }, outputs: new[] { output }); if (session!=null) { session.Dispose(); } if (tensor!=null) { tensor.Dispose(); } if (graph!=null) { graph.Dispose(); } GC.Collect(); GC.WaitForPendingFinalizers(); GC.Collect(); return normalized[0]; }
檢視Dispose程式碼行,銷燬就不洩露了。不銷燬就洩露。
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
有必要時用上邊3行程式碼回收記憶體。
const int W = 224; const int H = 224; const float Mean = 117; const float Scale = 1; graph = new TFGraph(); input = graph.Placeholder(TFDataType.String); output = graph.Div( x: graph.Sub( x: graph.ResizeBilinear( images: graph.ExpandDims( input: graph.Cast( graph.DecodeJpeg(contents: input, channels: 3), DstT: TFDataType.Float), dim: graph.Const(0, "make_batch")), size: graph.Const(new int[] { W, H }, "size")), y: graph.Const(Mean, "mean")), y: graph.Const(Scale, "scale")); GC.Collect(); GC.WaitForPendingFinalizers(); GC.Collect();