1

我在我的 Android 项目中使用 DL4J 来运行 CNN 网络作为分类器。问题是这个 CNN 模型占用的内存超过了我智能手机允许的每个应用程序堆大小,这导致内存不足错误。所以,我想知道是否有一种方法可以显式释放这个本机 DL4J 代码分配的内存。

安卓分析器

在此处输入图像描述

我的输入总共是 200 个图像补丁。我需要将它们堆叠在一起,以便处理时间更快。我尝试将批量大小设置为 32,因此每个输入 INDARRAY 的大小为 [32、3、44、44]。我也尝试过 16、8 等。但唯一没有出现内存不足错误的情况是我一次输入一个图像补丁。但我不能承受它导致的长处理时间。

我尝试使用 GC 显式释放内存,但它不起作用,这是有道理的,因为内存是由本机代码占用的。

for (int i = 0; i < N / UtilsCustom.NN_batch_size; i++) {
                                INDArray temp = UtilsCustom.overallArray.get(NDArrayIndex.interval(i * UtilsCustom.NN_batch_size, i * UtilsCustom.NN_batch_size + UtilsCustom.NN_batch_size), NDArrayIndex.all(), NDArrayIndex.all(), NDArrayIndex.all());
                                NN_classify(temp);
                                a = i * UtilsCustom.NN_batch_size + UtilsCustom.NN_batch_size;

                                if (i%2==1){
                                    model = null;
                                    java.lang.System.gc();
                                    Log.d(TAG, "GCGCGC");
                                    try {
                                        Thread.sleep(1000);
                                    } catch (InterruptedException e) {
                                        e.printStackTrace();
                                    }

                                    loadNNModel();
                                }

                                temp = null;
                                java.lang.System.gc();
                            }

private void NN_classify(INDArray imageMat) {

        int result;

        DataNormalization scaler = new ImagePreProcessingScaler(0, 1);
        scaler.transform(imageMat);

        INDArray output = model.output(imageMat);

        Log.d(LOG_TAG, "output.size(): " + output.size(0) + ", " + output.size(1));

        double prob_parasitemic = 0, prob_uninfected = 0;

        for (int i = 0; i < output.size(0); i++) {
            prob_parasitemic = output.getDouble(i, 0);
            prob_uninfected = output.getDouble(i, 1);
            Log.d(LOG_TAG, "prob_parasitemic: " + i + " " + output.getDouble(0, 0));
            Log.d(LOG_TAG, "prob_uninfected: " + i + " " + output.getDouble(0, 1));
        }

        if (prob_parasitemic > prob_uninfected) {
            result = 2;
        } else {
            result = 1;
        }

        Log.e(LOG_TAG, "Result: " + result);

        imageMat = null;
        output = null;
        java.lang.System.gc();
    }
4

1 回答 1

1

java.lang.System.gc()不做你认为它做的事。它不像 C 中的 free 或 C++ 中的 delete。

对 JVM 运行垃圾回收来说,它更像是一个“建议”。它不会强制垃圾收集或释放内存。

参考这个:https ://stackoverflow.com/a/66573/9241296

它指出,

我不会在您的代码中依赖它。如果 JVM 即将抛出 OutOfMemoryError,调用 System.gc() 不会阻止它,因为垃圾收集器会在它达到那个极端之前尝试尽可能多地释放它。

于 2018-02-13T17:15:10.400 回答