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


von Timmo H. (masterfx)


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?

von Peter (Gast)


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?

von Timmo H. (masterfx)


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.

von Peter (Gast)


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.

von kruemeltee (Gast)


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

von Rufus Τ. F. (rufus) Benutzerseite


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!"

von Timmo H. (masterfx)


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.

von Arc N. (arc)


Lesenswert?

1
void Throttle(DWORD percent) {
2
    for (int i = 0; i < 10; i++) {
3
        DWORD t = GetTickCount();
4
        while (GetTickCount() < t + percent) {
5
        }
6
        Sleep(100 - percent);
7
    }
8
}

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.

von Timmo H. (masterfx)


Lesenswert?

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

von Timmo H. (masterfx)


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?

von Sid (Gast)


Lesenswert?

Wie von Arc Net schon beschrieben geht das mit:
SetProcessAffinityMask und SetThreadAffinityMask ;)

von Vlad T. (vlad_tepesch)


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

von Timmo H. (masterfx)


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.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.