Forum: Mikrocontroller und Digitale Elektronik Programm für Busy Waiting, also nur NOP


von Erwin M. (nobodyy)


Lesenswert?

Busy Waiting sollte man ja möglichst vermeiden weil damit CPU-Zeit
verschwendet wird und es mehr Stromverbrauch bewirkt weil damit die 
Sleep States und auch Runtertakten abgestellt wird.
Aber machmal ist es doch sinnvoll, beispielsweise um die baldige 
Schaltsekunde aufzuzeichnen, denn dabei weiß man man ja nicht ob denn 
Funktionen wie sleep das machen was sie sollen, wie sie Zeitdifferenzen 
tatsächlich berechnen, und bei Busy Waiting hat man diese Ungewissheit 
nicht, zumindest wenn der Rechner nicht von anderem stark ausgelastet 
wird.
1
// With a 2.93 GHz core (Intel i7) 1e8 loops are done in 1.45 seconds, so one loop has a duration of about 15 ns.
2
// Compile without optimisation, e. g. with gcc -O0 -o nops nops.c.
3
4
#include <stdlib.h>
5
6
#define NOP100() asm volatile ("nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop")
7
8
int
9
main (int argc, char * argv[])
10
{
11
  long int li= argc > 1 ? strtol(argv[1], (char **)NULL, 0) : 0;
12
13
  if (li < 0) // limitation
14
    li = 0;
15
16
  for (;li >=0;li--) // count down
17
  {
18
    NOP100();
19
  }
20
  return(0);
21
}

Sinnvoll ist es, als eine separate Funktion die nicht main ist, wenn der 
Platz nicht für einen Scheduler reicht, z. B. wenn man nur 256 Byte RAM 
und 1 KiB Flash für den gesamten Code hat, so das man kein sleep 
implementieren kann.

Andere Anwendungen sind sanftes CPU burning, also Heizen per Software, 
und Rechner-Auslastung, beispielsweise um zu Testen wie stark 
Echtzeit-Prozesse durch andere beeiträchtigt werden oder wie sich der 
Rechner verhält wenn viele (hunderte bis tausende) solcher Prozesse 
laufen.

Es eignet sich auch zum Vermindern von Störabstrahlung, denn es gibt ja 
Angriffe die aus der schwankenden Stromaufnahme/Abstrahlung der CPU beim 
Verschlüsseln/Entschlüsseln basieren (Side-Channel-Attacks) und wenn man 
ständig für volle CPU-Auslastung sorgt, schwankt fast nichts mehr oder 
zumindest viel weniger.

Das Programm lastet nur einen Core aus.
Für mehrere Cores kann man es mehrmals starten und beispielsweise mit 
taskset oder numactl jeweils einem Core oder NUMA Node zuweisen.
Ich habe es bisher auf 32- und 64-Bit-PCs verwendet, unter Linux und 
Windows, aber es sollte auf jeder Plattform laufen.
Mit einem passenden Compiler müsste es auch auf GPU Cores laufen.

Unter 64Bit ist long int ja normalerweise 64 Bit lang, so das man bei 
dem Programm auch Wartezeiten von Jahren einstellen kann.

: Bearbeitet durch User
von foo (Gast)


Lesenswert?

Erwin M. schrieb:
> Andere Anwendungen sind sanftes CPU burning, also Heizen per Software

Wenn du nur Nops durchjagst, sind doch kaum Einheiten in der CPU aktiv. 
Ich würde dafür mindestens irgendwas mit SSE machen, dann haben die 
Floating Point Einheiten auch was zu tun.

Zudem führen die CPUs seit Jahren nicht exakt den Code aus den du ihnen 
hinwirfst, die optimieren da auch noch ein bisschen rum. Mich würde 
nicht wundern wenn das bei deinen Nops nicht auch passieren würde.

> Es eignet sich auch zum Vermindern von Störabstrahlung, denn es gibt ja
> Angriffe die aus der schwankenden Stromaufnahme/Abstrahlung der CPU beim
> Verschlüsseln/Entschlüsseln basieren (Side-Channel-Attacks)

Gegen Sidechannel Attacks schirmt man die Kiste ordentlich ab, und man 
nimmt Code, dessen Laufzeit Stromaufnahme etc. von den verarbeiteten 
Daten völlig unabhängig ist. Wenn du irgendwo Nops einstreust, kannst du 
die von anderen Instruktionen, die tatsächlich Daten verarbeiten, 
unterscheiden.

von Erwin M. (nobodyy)


Lesenswert?

Hier ist ein Beispiel für Sidechannel Attacks:

http://heise.de/-2721449

Die Hardware strahlt halt.

Und so kann man das Verhalten bei Schaltsekunden aufzeichnen, unter 
Linux in der Bash, unter Windows mittels Cygwin:

while true; do ./nops 23456789; date --utc +"%Y-%m-%d %H:%M:%S.%3N" >> 
leapseconds.txt; done

Für die lokale Zeit läßt man das --utc weg.

: Bearbeitet durch User
von Rolf F. (Firma: G.) (benutzername0)


Lesenswert?

Unter Ubuntu 64bit und Cygwin 32bit siehe ich keine Schaltsekunde; die 
wird einfach ignoriert.
Über NTP oder PTP (wenn installiert u. konfiguriert u. gestartet) wird 
das zwar im Lauf der Zeit korrigiert, aber das ist bei jedem Rechner 
etwas anders und wenn man mit Mikrosekunden-Auflösung arbeitet stimmen 
dann die Zeiten nicht.
Bei Schnittstellen wie dem Parallelport hat man ja unter 2 µs Latzenz, 
da stört es schon deutlich das die Sekunde 23:59:60 UTC unterschlagen 
wurde.

von foo (Gast)


Lesenswert?

Die Schaltsekunde führt in den betreffenden Fällen nicht zu Bugs.

Soweit ich das weiß, läuft sleep etc. letztendlich über eine Taktquelle, 
die von CPU oder Chipsatz oder so kommt - jedenfalls nicht über die Real 
Time Clock. Und die Timer auf der CPU wissen nix von irgendeiner Uhrzeit 
und damit auch nichts von Schaltsekunden. Die kennen nur "x Ticks seit 
Booten"

Wer sich natürlich seine Sleep-Routine über eine Busy Loop mit 
gettimeofday() zusammenfrickelt, der braucht sich auch nicht zu wundern, 
dass das einmal pro Halbjahr eine Sekunde länger dauert.

Es gibt ansonsten noch die clock_* Funktionen, bei denen man sich die 
Zeitquelle aussuchen kann, mindestens zwischen "normaler" Zeit und 
irgendeiner kontinuierlichen Zeit (meist Zeit seit Booten) kann man sich 
da entscheiden. Wenn man dann sein 2us Timing für seinen Parallelport 
einhalten muss, guckt man besser in die Doku und weiß dann, warum 
clock_nanosleep mit CLOCK_REALTIME eine eher dumme Idee ist.

Klar wir können die Schaltsekunden auch abschaffen. Ist bestimmt total 
lustig wenn Sonnentag und Kalendertag nach und nach auseinanderlaufen.

von Karl H. (kbuchegg)


Lesenswert?

foo schrieb:

> Wer sich natürlich seine Sleep-Routine über eine Busy Loop mit
> gettimeofday() zusammenfrickelt, der braucht sich auch nicht zu wundern,
> dass das einmal pro Halbjahr eine Sekunde länger dauert.

Wenns nur eine Sekunde wäre.
In der Nacht in der die Zeitumstellung Winterzeit/Sommerzeit erfolgt, 
passieren dann die tollsten Sachen.

von Rolf F. (Firma: G.) (benutzername0)


Lesenswert?

Karl H. schrieb:
>
> In der Nacht in der die Zeitumstellung Winterzeit/Sommerzeit erfolgt,
> passieren dann die tollsten Sachen.

Ja, deshalb nehme ich, wie auch für Server generell empfohlen, die UTC, 
https://de.wikipedia.org/wiki/Koordinierte_Weltzeit

Da gibt es keine Winterzeit/Sommerzeit und das ist auch gut so, denn bei 
W/SZ ist die Zeitangabe nicht eindeutig, zumindest die numerische 
Zeitangabe, und zudem hat man da große Zeitsprünge, währen bei der UTC 
nichts schwankt, denn die Schaltsekunde ist nur die Sekunde 60, also die 
einundsechzigste Sekunde einer Minute, so dass bei einer Schaltsekunde 
nichts vor- oder zurückspringt; die UTC ist streng monoton steigend und 
konstant steigend.

Ein weiterer Grund ist das ich auf Reisen nichts umstellen muss, z. B. 
am Notebook; die UTC ist in jedem Land gleich.

Bei der nächsten Umstellung lasse ich mal die while-Schleife über Nacht 
laufen einmal mit und einmal ohne --utc.

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Rolf F. schrieb:
> Ein weiterer Grund ist das ich auf Reisen nichts umstellen muss, z. B.
> am Notebook; die UTC ist in jedem Land gleich.

 LOL.
 Nur noch die Banken und Ladeninhaber in diesen Landern davon
 informieren, dass du von denen erwartest sich nach der UTC und nicht
 nach der lokalen Zeit zu richten.

 BTW:
 GMT und CET sind auch in allen Landern gleich.

: Bearbeitet durch User
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.