www.mikrocontroller.net

Forum: PC-Programmierung [C, WinAPI] Definierbare CPU-Last erzeugen


Autor: Timmo H. (masterfx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo.
Ich habe für Testzwecken ein Programm geschrieben, was mit variabler 
Thread-Anzahl ein oder mehrere Cores zu 100% auslastet. Wenn ich also 4 
Cores habe und 75% Auslastung erzeugen will dann erstelle ich eben 3 
Threads, wodurch 3 Cores zu 100% ausgelastet sind und die Systemlast 
entsprechend 75% beträgt.
Nun ist es aber so, dass wenn ich nur einen Core habe, die CPU-Last 
immer 100% ist. Jetzt würde ich gerne versuchen meinen Thread so zu 
modifizieren, dass er kurzzeitig, je nach gewünschter Auslastung, die 
Rechenzeit wieder freigibt, sodass ich auch z.B. eine Auslastung von 63% 
erzeugen kann.
Mit Sleep() geht das nicht, weil da die Auflösung nur etwa 15,6ms 
beträgt was natürlich viel zu lang ist. Alle anderen Warteschleifen 
geben jedoch die Rechenzeit nicht wieder frei.
Gibt es da eine Möglichkeit das irgendwie hinzubekommen?

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
warum sollte man sotwas überhaupt machen? Was heist überhaupt 100% 
auslasung. Wenn die CPU nicht zu tun hat denn schläft sie. Sie wird also 
runter getaktet. Bezieht sich die 100% nun auf die maximale Leistung der 
CPU oder auf die Leistung die sie zu diesem Zeitpunkt hat?

Autor: Timmo H. (masterfx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Peter schrieb:
> warum sollte man sotwas überhaupt machen?
Es geht darum, einem anderen Prozess gezielt eine gewisse CPU-Rechenzeit 
zu "stehlen" um zu sehen welche Auswirkungen das hat.
> Wenn die CPU nicht zu tun hat denn schläft sie. Sie wird also
> runter getaktet.
Das passiert nur wenn 1. die CPU das unterstützt und zweitens wenn es 
auch aktiviert ist. Das ist bei mir jedoch nicht der Fall.

> Bezieht sich die 100% nun auf die maximale Leistung der
> CPU oder auf die Leistung die sie zu diesem Zeitpunkt hat?
Auf die maximale Leistung der CPU. Mit meinem Programm schaffe ich es 
die 2x80W TDP von zwei Intel Xeon E5530 ziemlich genau zu erreichen, 
demnach arbeiten die Recheneinheiten der CPU schon sehr intensiv.

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Timmo H. schrieb:
>> warum sollte man sotwas überhaupt machen?
> Es geht darum, einem anderen Prozess gezielt eine gewisse CPU-Rechenzeit
> zu "stehlen" um zu sehen welche Auswirkungen das hat.

aber selbst wenn du die CPU zu 100% auslastest, geht ja immer noch 
einiges. Also lastest du sie ja nicht zu 100% aus. Wenn du die gleiche 
Priorität wie der andere Prozess hast. Dann schaffst du auch nur eine 
50% Auslastung selbst wenn du ohne sleep nur eine schleife machst.

Autor: kruemeltee (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Um das zu erreichen musst erst einmal herausfinden wieviele 
"Last-Anweisungen" dein Programm auf der CPU maximal hinbekommt in einem 
bestimmten Zeitraum.

Wenn das z.B. 10 pro Sekunde sind und du willst 50% Auslastung dann 
lässt du eine "Last-Anweisung" laufen, dann eine Pause von der Länge 
einer "Last-Anweisung", dann ...

Autor: Rufus Τ. Firefly (rufus) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Timmo H. schrieb:
> Mit Sleep() geht das nicht, weil da die Auflösung nur etwa 15,6ms
> beträgt was natürlich viel zu lang ist.

Die Granularität des Windows-Schedulers beträgt 10 msec und lässt sich 
auch auf 1 msec reduzieren. Das geht mit der Multimedia-Funktion 
timeBeginPeriod

Beitrag "Re: Phänomen: Software schneller, wenn Media-Player läuft!"

Autor: Timmo H. (masterfx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Also eigentlich würde mir ein Sleep_us() ja schon was bringen, aber das 
gibts halt nicht. Zumal Windows eben auch kein Echtzeit OS ist.
Vielleicht stricke ich das alles nochmal um, sodass ich nicht ca. 20000 
Durchläufe/s habe sondern nur noch 100 oder so, dann kann ich evtl. mit 
Sleep arbeiten.

@Rufus
Danke, das ist schonmal besser.

Autor: Arc Net (arc)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
void Throttle(DWORD percent) {
    for (int i = 0; i < 10; i++) {
        DWORD t = GetTickCount();
        while (GetTickCount() < t + percent) {
        }
        Sleep(100 - percent);
    }
}

Sowas erzeugt hier relativ gut (+-5%) die entsprechende Last.
Ansonsten QueryPerformanceFrequency, QueryPerformanceCounter und das 
schon erwähnte timeBeginPeriod
Bei mehreren Cores/CPU kommen noch SetProcessAffinityMask und 
SetThreadAffinityMask hinzu.

Autor: Timmo H. (masterfx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Arc Net,
das sieht doch schonmal gut aus, ich werde es morgen mal testen.

Autor: Timmo H. (masterfx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
So ich habe es gerade mal getestet. Das funktioniert bis ca. 40% 
erstaunlich genau. Das reicht mir eigentlich schon. Danke schonmal 
dafür!

Jetzt habe ich durch das Sleep jedoch ein Problem dazugewonnen, während 
des Sleeps kann Windows den Thread auf einen anderen Core auslagern, was 
es natürlich auch macht, sodass jeder Core im Schnitt etwa gleich stark 
ausgelastet ist. Klar nun könnte ich über den Taskmanager die 
Zugehörigkeit auf einen Core begrenzen. Jedoch wäre das Automatisch 
natürlich wesentlich komfortabler, vorallem bei einem 16-Core System :D
Kann man das irgendwie bewerkstelligen?

Autor: Sid (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wie von Arc Net schon beschrieben geht das mit:
SetProcessAffinityMask und SetThreadAffinityMask ;)

Autor: Vlad Tepesch (vlad_tepesch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
da gibt es tools für, google doch mal, mir fällt grad kein Name ein.

Wenn du es selber machen willst, würde mir folgendes einfallen:

so eine Art PWM, in der du das Tastverhältnis änderst:
du suchst dir eine Zeiteinheit, zB 50ms

Je nach gewünschter CPU-Auslastung

x = 50*prozentualeAuslastung/100


sleep(50-x); // keine CPU-Belastung

//timer aufsetzen, der in (x) ms flag setzt
while(!flag){   // 100% CPU-Belastung
}


und das in Endlossschleife

Autor: Timmo H. (masterfx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sid schrieb:
> Wie von Arc Net schon beschrieben geht das mit:
> SetProcessAffinityMask und SetThreadAffinityMask ;)
Tatsache, hab ich doch glatt überlesen :D
Vielen dank euch allen, ich denke das Problem ist gelöst.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.