CPU-Kern voll ausnutzen

Luk10

Top Contributor
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

Top Contributor
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.ä.
 

Marco13

Top Contributor
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
Java:
double d = 0;
while (true) d += Math.sin(d);
in einem Thread dürfte für 100% sorgen - ein
Java:
while (true) downloadSomeFileViaModem();
eher nicht ;)
 

Luk10

Top Contributor
Java:
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

Bekanntes Mitglied
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

Bekanntes Mitglied
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 :p)?

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

Bekanntes Mitglied
Java:
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-

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".
 
B

bone2

Gast
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

Top Contributor
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

Bekanntes Mitglied
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 ^^):

Java:
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:

Java:
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:

kmeans4threads.jpg
 
Zuletzt bearbeitet:

Blackhole16

Bekanntes Mitglied
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

Top Contributor
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-
 

Luk10

Top Contributor
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.
 
J

JohannisderKaeufer

Gast
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

Top Contributor
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]
 
Zuletzt bearbeitet:

Lumaraf

Bekanntes Mitglied
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.
 

Ähnliche Java Themen

Neue Themen


Oben