2013-12-20 77 views
0

我已经创建了一个方法来基于从服务器获得的Http响应填充数组。我以简单的格式收到回复,并使用扫描仪读取。响应只有大约8000个条目(浮点数和整数),并且需要大约1或2分钟才能填充ArrayList。这里是代码填充ArrayList中的Android性能问题

public void update(String str) { 
    ProgressDialog pDialog = new ProgressDialog(context); 
    pDialog.setMessage("Atualizando pesos, aguarde"); 
    pDialog.show(); 
    BufferedReader r = new BufferedReader(new StringReader(str)); 
    Scanner s = null; 
    try{ 
     s = new Scanner(r); 
     ArrayList<ArrayList<ArrayList<Double> > > weights = new ArrayList<ArrayList<ArrayList<Double> > >(); 
     while(s.hasNextInt()){ 
      ArrayList<ArrayList<Double> > wl = new ArrayList<ArrayList<Double> >(); 
      int layerId = s.nextInt(), neuronsAmt = s.nextInt(), inputSize = s.nextInt(); 
      Log.d("UpdateTask", "Layer " + layerId + ", neuronios: " + neuronsAmt + ", inputSize: " + inputSize); 
      for(int i = 0; i < neuronsAmt; i++){ 
       ArrayList<Double> wi = new ArrayList<Double>(); 
       for(int j = 0; j < inputSize; j++){ 
        wi.add(s.nextDouble()); 
       } 
       wl.add(wi); 
      } 
      weights.add(wl); 
      this.weights = weights; 
      if(s.hasNext() && !s.hasNextInt()) 
       Log.d("UpdateTask", "Depois de tudo tem " + s.next()); 
     } 
    }finally{ 
     if(s != null) s.close(); 
     pDialog.dismiss(); 
    } 
} 

我收到HTTP响应后从AsyncTask调用它。

编辑:我会尽力在这里解释HTTP结构。响应实际上给出了神经网络的权重。基本上它是一组矩阵(它应该保持为矩阵,以评估神经网络的工作情况)。 HTTP响应如下: 有N个矩阵。每个以一个整数(矩阵ID)开头,后面跟着矩阵中的行数(R)和列数(C)。之后,有R * C浮点数表示存储在矩阵中的值。当您找不到其他图层ID时,输入会终止。

PS:我无法使对话框工作,但这对我来说现在不是问题。

+1

? – ThaMe90

+0

它实际上是一个矩阵数组(这是我试图做的神经网络中的权重)。我只是不知道更好的方法来做到这一点(我刚刚开始用Java编写代码)。 –

+0

嗯,我不知道确切的效果,但我可以想象这是非常低效的。 – ThaMe90

回答

0

在此处讨论的其他优化之后,结果会更好。 问题是扫描仪非常慢,在Android设备中它变得更慢。这可能是由于它在背景中产生的缓冲量,我不知道。

我已经使用了编程竞赛的技巧:标记输入字符串并逐个解析值。结果非常好:我可以在不到一秒的时间内填充ArrayList。

这是我现在得到的,伟大的工作:你为什么要使用一个ArrayList >>

... 
    String[] tokens = str.trim().split(" "); 
    weights = new ArrayList<Double[][]>(); 
    int begin = 0; 
    while(begin < tokens.length){ 
     int layerId = Integer.parseInt(tokens[begin]), neuronsAmt = Integer.parseInt(tokens[begin+1]), inputSize = Integer.parseInt(tokens[begin+2]); 
     begin += 3; 
     Double[][] wl = new Double[inputSize][neuronsAmt]; 
     Log.d("UpdateTask", "Layer " + layerId + ", neuronios: " + neuronsAmt + ", inputSize: " + inputSize); 
     for(int i = 0; i < inputSize; i++){ 
      for(int j = 0; j < neuronsAmt; j++){ 
       wl[i][j] = Double.valueOf(tokens[begin+i*neuronsAmt+j]); 
      } 
     } 
     begin += inputSize*neuronsAmt; 
     weights.add(wl); 
    } 
    ... 
0

如果你知道你ArrayList的条目数量(或者至少有一个线索)使用此容量安装它。像这样:

//N is the number of matrices that you are expceting 
ArrayList<ArrayList<ArrayList<Double> > > weights = new ArrayList<ArrayList<ArrayList<Double> > >(N); 
    while(s.hasNextInt()){ 

    ArrayList<ArrayList<Double> > wl = new ArrayList<ArrayList<Double> >(R); 
    int layerId = s.nextInt(), neuronsAmt = s.nextInt(), inputSize = s.nextInt(); 
    for(int i = 0; i < neuronsAmt; i++){ 
     ArrayList<Double> wi = new ArrayList<Double>(inputSize); 
      for(int j = 0; j < inputSize; j++){ 
       wi.add(s.nextDouble()); 
      } 
      wl.add(wi); 
    } 
+0

由于原始文章使用3个嵌套ArrayLists,我期望数据处于锯齿状的3d阵列中。 – ThaMe90

+0

嗯,这是一回事。只需用近似值来实例化每一个。 – leandrocastelli

+1

不,只需使用add函数 – leandrocastelli

1

考虑简化您的数组结构,即尽可能使用随机array。在可能的情况下(如提到的leandrocastelli),也可以初始化容量为ArrayList。例如,您的代码可能会以这种方式优化:

... 

    try { 
     s = new Scanner(r); 
     ArrayList<double[][]> weights = new ArrayList<double[][]>(); // capacity is highly recommended here, even approximate 
     while(s.hasNextInt()){ 

      int layerId = s.nextInt(), neuronsAmt = s.nextInt(), inputSize = s.nextInt(); 
      double[][] wl = new double[neuronsAmt][]; // just 2D-array of doubles, which is much faster than List of List 

      Log.d("UpdateTask", "Layer " + layerId + ", neuronios: " + neuronsAmt + ", inputSize: " + inputSize); 
      for(int i = 0; i < neuronsAmt; i++){ 
       double[] wi = new double[inputSize]; 
       for(int j = 0; j < inputSize; j++){ 
        wi[j] = s.nextDouble(); 
       } 
       wl[i] = wi; 
      } 
      weights.add(wl); 
      this.weights = weights; 
      if(s.hasNext() && !s.hasNextInt()) 
       Log.d("UpdateTask", "Depois de tudo tem " + s.next()); 
     } 
    } 
    ... 
+0

我知道应该改善它,但会造成严重的不同吗?我的意思是,在这个3D ArrayList中的项目总数大约是8000,它不应该有很大的区别,对吧?我的意思是,现在需要超过1分钟的时间来填充ArrayList。 –

+1

你应该尝试一下,它是简单明了的优化。为了100%确定造成滞后的原因,[profile](http://developer.android.com/tools/debugging/debugging-tracing.html)你的方法。 –

+0

接受“个人资料”提示的答案,谢谢,我会尽快尝试。 –