2012-07-31 16 views
6

Mam następujący kod:Java Parallel Processing File

import java.io.*; 
import java.util.concurrent.* ; 
public class Example{ 
public static void main(String args[]) { 
    try { 
     FileOutputStream fos = new FileOutputStream("1.dat"); 
     DataOutputStream dos = new DataOutputStream(fos); 

     for (int i = 0; i < 200000; i++) { 
      dos.writeInt(i); 
     } 
     dos.close();               // Two sample files created 

     FileOutputStream fos1 = new FileOutputStream("2.dat"); 
     DataOutputStream dos1 = new DataOutputStream(fos1); 

     for (int i = 200000; i < 400000; i++) { 
      dos1.writeInt(i); 
     } 
     dos1.close(); 

     Exampless.createArray(200000); //Create a shared array 
     Exampless ex1 = new Exampless("1.dat"); 
     Exampless ex2 = new Exampless("2.dat"); 
     ExecutorService executor = Executors.newFixedThreadPool(2); //Exexuted parallaly to cont number of matches in two file 
     long startTime = System.nanoTime(); 
     long endTime; 
     Future<Integer> future1 = executor.submit(ex1); 
     Future<Integer> future2 = executor.submit(ex2); 
     int count1 = future1.get(); 
     int count2 = future2.get(); 
     endTime = System.nanoTime(); 
     long duration = endTime - startTime; 
     System.out.println("duration with threads:"+duration); 
     executor.shutdown(); 
     System.out.println("Matches: " + (count1 + count2)); 

     startTime = System.nanoTime(); 
     ex1.call(); 
     ex2.call(); 
     endTime = System.nanoTime(); 
     duration = endTime - startTime; 
     System.out.println("duration without threads:"+duration); 

    } catch (Exception e) { 
     System.err.println("Error: " + e.getMessage()); 
    } 
} 
} 

class Exampless implements Callable { 

public static int[] arr = new int[20000]; 
public String _name; 

public Exampless(String name) { 
    this._name = name; 
} 

static void createArray(int z) { 
    for (int i = z; i < z + 20000; i++) { //shared array 
     arr[i - z] = i; 
    } 
} 

public Object call() { 
    try { 
     int cnt = 0; 
     FileInputStream fin = new FileInputStream(_name); 
     DataInputStream din = new DataInputStream(fin);  // read file and calculate number of matches 
     for (int i = 0; i < 20000; i++) { 
      int c = din.readInt(); 
      if (c == arr[i]) { 
       cnt++; 
      } 
     } 
     return cnt ; 
    } catch (Exception e) { 
     System.err.println("Error: " + e.getMessage()); 
    } 
    return -1 ; 
} 

} 

Gdzie Próbuję policzyć liczbę meczów w tablicy z dwoma plikami. Teraz, chociaż uruchamiam go na dwóch wątkach, kod nie działa dobrze, ponieważ:

(uruchamianie go w jednym wątku, plik 1 + plik 2 czas czytania) < (plik 1 || plik 2 czas czytania w wielu wątkach).

Czy ktoś może mi pomóc, jak to rozwiązać (mam 2 rdzeń procesora i rozmiar pliku to około 1,5 GB).

+0

@SurajChandran, większość czasu. I naprawdę bez efektu. :) Po prostu uruchom test. – Arpssss

+0

Pliki nie są 1,5 GB, mają tylko ~ 80K. –

+0

@KeithRandall, po prostu podam przykład użycia. – Arpssss

Odpowiedz

7

W pierwszym przypadku czyta się sekwencyjnie jeden plik, bajt po bajcie, blok po bloku. Jest to tak szybkie, jak dyskowe operacje we/wy, pod warunkiem, że plik nie jest bardzo pofragmentowany. Kiedy skończysz z pierwszym plikiem, system plików/OS odnajdzie początek drugiego pliku i kontynuuje bardzo wydajny, liniowy odczyt dysku.

W drugim przypadku stale przełączasz się między pierwszym a drugim plikiem, zmuszając dysk do szukania z jednego miejsca do drugiego. Ten dodatkowy czas poszukiwania (około 10 ms) jest źródłem twojego zamieszania.

Aha, i wiesz, że dostęp do dysku jest jednowątkowy, a twoje zadanie jest związane z I/O, więc nie ma sensu dzielenie tego zadania na wiele wątków może pomóc, tak długo, jak czytasz z tego samego dysku fizycznego? Twoje podejście mogłoby być uzasadnione tylko wtedy, gdy:

  • każdego wątku, z wyjątkiem czytania z pliku, wykonując również trochę obciąża CPU lub operacji wolniejszy blokowanie przez rząd wielkości w porównaniu z I/O.

  • pliki znajdują się na różnych fizycznych napędów (inna partycja nie wystarczy) lub na niektórych konfiguracjach RAID

  • używasz dysku SSD

+1

+1. Jest to podstawowy problem, którego wielu ludzi nie rozumie: zwiększenie odczynnika ograniczającego zwiększa wydajność. – RedGreasel

1

Nie dostaniesz żadnej korzyści z wielowątkowości jak zauważył Tomasz czytając dane z dysku. Możesz uzyskać pewną poprawę szybkości, jeśli wielowątkowe sprawdzanie, tj. Ładowanie danych z plików do tablic sekwencyjnie, a następnie wątki przeprowadzają sprawdzanie równolegle. Biorąc pod uwagę niewielki rozmiar plików (~ 80kb) i fakt, że po prostu porównujesz ints, wątpię, aby poprawa wydajności była warta wysiłku.

Coś, co zdecydowanie poprawi twoją szybkość wykonania, jeśli nie używasz metody readInt(). Ponieważ wiesz, że porównujesz 20000 ints, powinieneś przeczytać wszystkie 20000 ints w tablicy naraz dla każdego pliku (lub przynajmniej w blokach), zamiast wywoływać funkcję readInt() 20000 razy.