2013-12-20 76 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

接受「個人資料」提示的答案,謝謝,我會盡快嘗試。 –