# CPU-Kern voll ausnutzen



## Luk10 (23. Apr 2012)

Grüße,

Ich einen recht performance-lastigen Thread, der viele Berechnungen ausführen muss (läuft in Schleife).

Das Resultat ist leider zur Zeit wenig befriedigend, da es sehr lange dauert bis ein Schleifen-Durchlauf ausgeführt wurde. Mir ist außerdem aufgefallen, dass der CPU-Kern auf dem das Programm läuft nur zu etwa 20% ausgelastet ist, die restlichen Kerne auf +-5%.

Wie kann ich es schaffen, dass dieser eine Kern stärker ausgelastet wird und ich damit eine bessere Performance bekommen kann?

Danke,
-Luk10-


----------



## pl4gu33 (23. Apr 2012)

also das is jetzt eher auf mehrere Kerne bezogen... wenn die Berechnungen unabhängig sind, könntest du sie direkt auf mehrere Kerne verteilen und dann zum Schluss (mit join aufeinander warten ) zusammenrechnen o.ä.


----------



## Volvagia (23. Apr 2012)

Greifst du vielleicht auf etwas synchronisiertem zu?


----------



## Marco13 (23. Apr 2012)

Wenn die eine CPU mit einem voll beschäftigten Thread nicht qualmt, liegt das "zwangsläufig" (!?!) daran, dass er die Daten nicht schnell genug bekommt... Ein

```
double d = 0;
while (true) d += Math.sin(d);
```
in einem Thread dürfte für 100% sorgen - ein

```
while (true) downloadSomeFileViaModem();
```
eher nicht


----------



## Luk10 (23. Apr 2012)

```
double d = 0;
while (true) d += Math.sin(d);
```

Sorgt bei mir für eine Gesamt-Auslastung von 25% (relativ gleichmäßig auf 4 Kerne verteilt, obwohl es nur 1 Thread ist)

-Luk10-


----------



## Kaffeebohn (23. Apr 2012)

Bei mir sorgt das auch für eine "gleichmäßige" Auslastung aller Kerne. Wenn ich allerdings das ding 4. starte dann komme ich trotzdem auf in 25%er Schritten auf 100%. Scheint wohl daran liegen wie die Last auf die Kerne verteilt wird. Ich meine mich zu erinnern, dass man früher damit tatsächlich einen Kern auf 100% bekommen hat während die andren nichts getan  haben. Kann mich aber irren.

Grüße


----------



## Blackhole16 (24. Apr 2012)

Ich denke mal, dass die Prozessoren inzwischen schon zu intelligent sind, als dass man nur einen Kern ausnutzt.

Desweiteren hat man in Java genau 0!!! Rechte, was Systemwerte angeht. 

Wenn du dich extrem gut mit der Systemproggrammierung von windows auseinandersetzt, sollte es denke ich möglich sein, dass du mit Java und Adminrechten Dateien veränderst, die dafür zuständig sind. Aber das wird unmöglich, da Windows nicht open source ist und extrem stark verschlüsselt... Bei Linux würde das schon anders aussehen, aber ich denke nicht, dass es unbedingt notwendig ist. 

Was machst du denn in dem Code? Wie sieht der aus (aber bitte nicht 5k Zeilen posten )? 

Vielleicht könnte der Code nur verbessert werden, sodass das ganze schneller abläuft. Denn wenn der PC langsam wird, deutet das eigentlich auf Overhead hin... Oder nicht =?

mfg
BH16


----------



## Lumaraf (24. Apr 2012)

Luk10 hat gesagt.:


> ```
> double d = 0;
> while (true) d += Math.sin(d);
> ```
> ...



Ich vermute mal das hängt mit der automatischen Übertaktung von kalten Kernen in aktueller CPUs zusammen. Wenn man alle Kerne gleichmäßig auslastet hat man niedrigere Spitzentemperaturen in allen Kernen und somit mehr möglichkeiten zusätzliche Leistung durch die Erhöhung der Taktes herauszuholen. Intel nennt das btw "Turbo Boost" und AMD "Turbo Core".


----------



## bone2 (24. Apr 2012)

25% liegt einfach daran, das es nur auf einem kern/thread läuft. windows schiebt abwechseln den 4 kernen einen happen zum rechnen hin, sosnt würde einfach ein kern auf 100% laufen und der rest skat spielen. einfach mal in windows java gezielt nur einen kern zuweisen. gesamt auslastung bleibt 25%.

übertakten die intels nicht auch gut wenn nur ein kern was zu tun hat? ich erinnere mich dunkel an turbo für single core prozesse


----------



## irgendjemand (24. Apr 2012)

bone2 hat gesagt.:


> 25% liegt einfach daran, das es nur auf einem kern/thread läuft. windows schiebt abwechseln den 4 kernen einen happen zum rechnen hin, sosnt würde einfach ein kern auf 100% laufen und der rest skat spielen. einfach mal in windows java gezielt nur einen kern zuweisen. gesamt auslastung bleibt 25%.
> 
> übertakten die intels nicht auch gut wenn nur ein kern was zu tun hat? ich erinnere mich dunkel an turbo für single core prozesse



made my day ...

stellt euch das mal als neuen marketing gag vor : der neue SkatCore : 1 core arbeitet , die anderen 3 speilen Skat ... *boa ich würde so in der ecke liegen*


----------



## vimar (24. Apr 2012)

also da ich selber derzeit threadoptimierung mache in meinem programm und es vorher auch nur sozusagen auf einem kern lief mit auslastung 25% (quadcore) und da hatte sich das auch auf alle 4 kerne verteilt und ich hab auch gedacht: ja warum nutzt der nicht nur einen kern auf 100%? jedenfalls bei nem quadcore 25% auslastung heisst so oder so dass die leistung eines kerns irgendwo erreicht wird.


also ich weiss nicht genau was du da für ein programm hast aber ich habe immer folgende überlegung:

1. grundsätzlich ein thread für gui, ein thread für berechnungen, ein thread für das allgemeine zeug. soweit ist das sowieso klar denke ich.

2. bei rechenintensiven operationen würde ich schauen inwiefern sind die berechnungen abhängig von einander? falls die irgendwie unabhängig sind und man garnicht auf das ergebnis einer funktion warten muss um mit dem ergebnis die andere funktion aufzurufen kann man sowas durch 2 threads lösen und hat somit auch mehr auslastung. vllt ein bisschen code für uns alle damit wir uns das ansehen können.


Anmerkung: du meinst du hast ne schleife. sagen wir es ist ne for schleife. wenn jeder durchlauf irgendwie "unabhängig" ist von dem durchlauf zuvor, kannst du das so aufsplitten hier mein beispiel aber an alle professionellen programmierer hier: threads sind für mich auch neuland(seit 3 wochen) und jedenfalls hab ich hiermit volle auslastung aller 4 kerne. du hast einfach 4 threads, prüfst mit isAlive() ob die aktiv sind, falls nicht dann nehmen die ein stück der berechnung und machen ihren kram solang bis nix mehr da is (meine threads haben namen ^^):


```
while(ThreadManager.getAktZiegel() < ThreadManager.getMaxZiegel()){ // && das nochmal in if2,if3,if4
                    
                    
                    
                if (ThreadManager.getAktZiegel() < ThreadManager.getMaxZiegel()){    
                    
                    if((!(ThreadManager.getB1().isAlive())) && (ThreadManager.getAktZiegel() < ThreadManager.getMaxZiegel())){ // wenn der pennt!
                        ThreadManager.setB1(new KMEANS_CentroidRelocateThread(ClusterList,"Hugo",ThreadManager));
                        ThreadManager.getB1().aktZiegel = ThreadManager.getAktZiegel();
                        incZiegel();
                       // System.out.println("starte t1 letzte");
                        ThreadManager.getB1().start();
                    }
                    if((!(ThreadManager.getB2().isAlive())) && (ThreadManager.getAktZiegel() < ThreadManager.getMaxZiegel())){
                        ThreadManager.setB2(new KMEANS_CentroidRelocateThread(ClusterList,"Stefan",ThreadManager));
                        ThreadManager.getB2().aktZiegel = ThreadManager.getAktZiegel();
                       incZiegel();
                      //  System.out.println("starte t2 letzte");
                        ThreadManager.getB2().start();
                    }
                    if((!(ThreadManager.getB3().isAlive()))&& (ThreadManager.getAktZiegel() < ThreadManager.getMaxZiegel())){
                        ThreadManager.setB3(new KMEANS_CentroidRelocateThread(ClusterList,"Alex",ThreadManager));
                        ThreadManager.getB3().aktZiegel = ThreadManager.getAktZiegel();
                      incZiegel();
                        //System.out.println("starte t3 letzte");
                        ThreadManager.getB3().start();
                    }
                    if((!(ThreadManager.getB4().isAlive()))&& (ThreadManager.getAktZiegel() < ThreadManager.getMaxZiegel())){
                        ThreadManager.setB4(new KMEANS_CentroidRelocateThread(ClusterList,"Johannes",ThreadManager));
                        ThreadManager.getB4().aktZiegel = ThreadManager.getAktZiegel();
                      incZiegel();
                       // System.out.println("starte t4 letzte");
                        ThreadManager.getB4().start();
                    }
                    
                  
                   
                }
                    
                    
                    
                }
```


und damit es nicht zu problemen kommt beim inkrementieren:


```
public synchronized void incZiegel(){

          ThreadManager.setAktZiegel(ThreadManager.getAktZiegel()+1);

      }
```

muss das inkrementieren in ner synchronized methode gemacht werden.

ich denke mal du willst so eine auslastung deswegen zeig mal ein bissl code:


----------



## Blackhole16 (24. Apr 2012)

irgendjemand hat gesagt.:


> made my day ...
> 
> stellt euch das mal als neuen marketing gag vor : der neue SkatCore : 1 core arbeitet , die anderen 3 speilen Skat ... *boa ich würde so in der ecke liegen*



[OT]Würde es hier ein Like-Button geben, hätte ich mich 10X registriert, nur um das zu liken )))) 
Ich finds einfach nur :lol::lol::lol::lol::lol::lol::lol::lol::lol::lol::lol::lol::lol::lol::lol::lol::lol::lol::lol:[/OT]

btw: also made my day

mfg BH16


----------



## Luk10 (26. Apr 2012)

So ich will jetzt doch alle vier Kerne nutzen und muss mich wohl deshalb an Mulit-Threading ranwagen.

Ich habe meine Objekte in einer ArrayList. Zur berechnung brauchen die Objekte nur eine gemeinsame Ressource, die dann wohl sychronisiert werden muss.

Leider hilft mir "Java ist auch eine Insel" nicht besonders viel weiter, und auch der Beispiel-Code hier erklärt nicht wirklich wie man das am besten anstellt.

Kann mir jemand ein Beispiel verlinken oder mir eine Erklärung bieten wie und wo ich Threads initialisiern muss, wie lange sie laufen (in Endlosschleife?), wann sie join(en) und alles von Grund auf am besten.

Danke,
-Luk10-


----------



## JohannisderKaeufer (26. Apr 2012)

> eine gemeinsame Ressource



Was verstehst du darunter?


----------



## Luk10 (26. Apr 2012)

Eine Instanzvariable in einer Klasse, die von den Objekten in der ArrayList verändert wird.

Ist es wirklich so gedacht, dass ich pro Schleifen-Durchlauf 4 neue Threads erzeuge? Kommt mir sehr unsinnig vor.


----------



## JohannisderKaeufer (26. Apr 2012)

Ok, es kommt allerdings darauf an wie deine "Transaktionen" sind.

Je nachdem wie das aussieht, kann es möglich sein, dass es garnicht möglich ist etwas zu parallelisieren.

Nehmen wir an deine Ressource wäre ein Kontostand und in deiner Liste hättest du Abbuchungsaufträge die diesen verändern.

Hier macht es wenig Sinn, das ganze mithilfe von Threads zu parallelisieren, da Kontostandsabfrage und  Veränderung in einer Transaktion gebündelt synchronisiert gehören.

Ein Beispiel ohne sync.

Kontostand: 1000
T1(Thread) kAbfrage: 1000
T2 kAbfrage: 1000:
T1 abbuchung: 100, berechnung neuer Kontostand auf Basis 1000: 900
T2 abbuchung: 50, berechnung neuer Kontostand auf Basis 1000: 950
Kontostand: 950

Mit sync.
Kontostand: 1000
synchronized{
T1(Thread) kAbfrage: 1000
T1 abbuchung: 100, berechnung neuer Kontostand auf Basis 1000: 900
}
synchronized{
T2 kAbfrage: 900:
T2 abbuchung: 50, berechnung neuer Kontostand auf Basis 900: 850
}
Kontostand: 850


Man könnte allerdings eine Sammelbuchung in den einzelnen Threads berechnen so daß der Kontostand dann in diesem Beispiel nur einmalig um 150 reduziert wird.


----------



## Luk10 (26. Apr 2012)

Es handelt sich um eine Bitmap (innerhalb: int[] pixels) auf das sich das jeweilig Objekt zeichnet. Da es sich um die screen-Bitmap handelt, muss jedes Objekt drauf zugreifen und sich selbst draufzeichnen.

[EDIT]Das überblenden von Pixeln kostet relativ viel Performance, also wollte ich das mit Multi-Threading beschleunigen.
Die Objekte in der Liste sollen sich nacheinander und unabhängig von einander auf die übergebene gemeinsame Resource zeichnen.[/EDIT]


----------



## Lumaraf (26. Apr 2012)

Wenn es nur darum geht viele Grafik mit Überlagerungen zu einem Gesamtbild zusammenzufügen wäre die GPU deutlich schneller als die CPU. Für Java gibt es diverse OpenGL Wrapper mit dem sich sowas umsetzen lassen müßte.


----------

