2015-02-17 12 views
8

Ho effettuato alcuni test un anno fa riguardo il multicore con java 7. Innanzitutto ho implementato alcuni calcoli solo nel thread principale (l'utilizzo della CPU ha mostrato che solo un core eseguiva tutto il lavoro) e quindi ho implementato Callable con un'istanza di ExecutorService. Mentre esegue tutti i core dove si fa il lavoro.Java 8 utilizza automaticamente il multicore?

Ora, un anno dopo, devo implementare un programmino (usando java 8) che interpola un sacco di dati. Tutto il lavoro è implementato nel thread principale (senza Callable ed ExecutorService) ma quando eseguo il programma l'utilizzo della CPU mi mostra che tutti e 4 i core sono al 98%.

Quindi java 8 distribuisce automaticamente il lavoro su tutti i core della CPU? Sono confuso ...

Qui po 'di codice ...

MapGenerator.java

Region[][] regions = new Region[numOfRegions][numOfRegions]; 

    for(int x = 0; x < regions.length; x++){ 
     for(int z = 0; z < regions[x].length; z++){ 
      newLat = SRTMHandler.getNewLatitude(startLat, z * regionSize * 16); 
      newLon = SRTMHandler.getNewLongitude(startLon, x * regionSize * 16, newLat); 

      regions[x][z] = new Region(x, z, regionSize, newLat, newLon); 
     } 
    } 

Region.java:

private Chunk[] chunks;  

public Region(int x, int z, int size, float startLat, float startLon){ 
    this.chunks = new Chunk[this.size][this.size]; 
    //Init stuff 
    float newLat = this.startLat, newLon = this.startLon; 

    for(int newX = 0; newX < this.size; newX++){ 
     for(int newZ = 0; newZ < this.size; newZ++){ 
      newLat = SRTMHandler.getNewLatitude(this.startLat, newZ * 16); 
      newLon = SRTMHandler.getNewLongitude(this.startLon, newX * 16, newLat); 

      this.chunks[newX][newZ] = new Chunk(this.x * this.size + newX, this.z * this.size + newZ, 16, 900, this, newLat, newLon); 
     } 
    } 
} 

Chunk.java: (SRTMHandler.getHeightForLatLon() esegue alcuni calcoli geografici e quindi legge un valore in un array di byte, niente di speciale)

public Chunk(int x, int z, int size, int height, Region r, float startLat, float startLon){ 
    this.blocks = new Block[size][size][height]; 
    //Init stuff 

    try { 
     this.calcSurface(); 
     //System.out.println("Finished " + this.toString()); 
    } catch (IOException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 
} 

private void calcSurface() throws IOException{ 
    int x1 = this.x; 
    int x2 = this.x + 16; 
    int z1 = this.z; 
    int z2 = this.z + 16; 
    final int radius = 45; 
    float q11 = SRTMHandler.getHeightForLatLon(SRTMHandler.getNewLatitude(this.startLat, (-1)*radius), SRTMHandler.getNewLongitude(this.startLon, (-1)*radius, this.startLat)); 
    float q12 = SRTMHandler.getHeightForLatLon(SRTMHandler.getNewLatitude(this.startLat, radius), SRTMHandler.getNewLongitude(this.startLon, (-1)*radius, this.startLat)); 
    float q21 = SRTMHandler.getHeightForLatLon(SRTMHandler.getNewLatitude(this.startLat, (-1)*radius), SRTMHandler.getNewLongitude(this.startLon, radius, this.startLon)); 
    float q22 = SRTMHandler.getHeightForLatLon(SRTMHandler.getNewLatitude(this.startLat, radius), SRTMHandler.getNewLongitude(this.startLon, radius, this.startLat)); 

    for(int x = 0; x < this.blocks.length; x++){ 
     for(int z = 0; z < this.blocks[x].length; z++){ 
      float height = Interpolation.biLerp(x, z, q11, q12, q21, q22, x1, x2, z1, z2); 

      this.blocks[x][z][(int)Math.round(height)] = new Block(this.x * this.size + x, this.z * this.size + z, (int)Math.round(height), BlockType.Grass, this); 
     } 
    } 
} 
+1

Si sta utilizzando le funzionalità di programmazione funzionale di Java 8, in particolare i flussi paralleli? – erickson

+1

Quando aparapi/parallelforall viene completamente fornito, anche gpus può essere utilizzato automaticamente usando codici java-only, lambda. –

+2

Potresti fornire un esempio di codice ridotto? –

risposta

5

Java 8 non distribuisce automaticamente il lavoro su tutti i core della CPU, a meno che il codice non lo richieda esplicitamente (ad esempio utilizzando flussi paralleli).

In alcuni casi speciali il compilatore Hotspot effettuerà il codice auto-vectorize, vedere ad esempio JDK-6340864. Tuttavia, la vettorizzazione automatica utilizza speciali istruzioni CPU SIMD, non più CPU.

vedere anche queste risposte:

(notare che ho riscritto la risposta, eliminando la parte che è stato corretto dai commenti)

+0

I compilatori eseguono una limitata auto-vettorizzazione, che è una forma di parallelizzazione automatica. – the8472

+0

Matlab esegue la parallelizzazione automatica quando si opera su matrici di grandi dimensioni. Utilizza tutti i core quando necessario. – rcpinto

1

ho sperimentato anche questa situazione. Nel mio caso, è la raccolta dei rifiuti frequente che causa un utilizzo significativo della CPU (98%). Come sottolineato da diversi commenti nelle domande originali, il GC java utilizza multi-threading per impostazione predefinita.

A mio parere, il programma non è collegato alla CPU. Pertanto, non è probabile che utilizzi completamente 4 core. D'altra parte, quando non c'è abbastanza spazio disponibile per il programma, il GC frequente esaurisce facilmente la risorsa della CPU. Dopo aver aumentato le dimensioni dell'heap, tutto va bene.