Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Timestamp Counter Frequenz unter /proc

1 view
Skip to first unread message

Bonita Montero

unread,
Jan 24, 2023, 8:35:52 AM1/24/23
to
Ich habe mir so eine C++-klasse geschrieben die eine thread-safe Warte-
schlange für Procucer-Conumer-Patterns (ein Thread schiebt etwas in eine
Queue, ein oder mehrere Threads entnehmen das dann) darstellt. Aktuell
habe ich das Problem, dass die Items mit hoher Frequenz dort eingefügt
werden und die Verarbeitungs-Semantik bei den Consumern so minimal ist,
dass diese auch mit der entsprechend hohen Frequenz abgebommen werden.
Daraus resultiert, dass die Synchronisation ne Menge Perfoemance frisst.
Auf jeden Fall dachte ich mir, ich schreibe die Queue jetzt um, dass die
eben erst N Elemente annimmt und ich eine Art Flush hinterherschicke,
dass die Items auch der Gegenseite signalisiert werden. Weil ich das
entsprechende Semaphor das hinter der Condition-Variable steht dann
nur einmal um N hochzählen muss (Geht unter Win32 und mit Posix- und
SysV-Semaphoren problemlos) würde ich ne Menge an CPU-Zeit sparen.
Ich hab mir gedacht, dass ich das Ganze dann noch ein wenig aufbohre
und sage, ab N Elementen wird sowieso geflusht, aber nach Ablauf der
Zeit t, also auch wenn weniger Elemente in der Queue liegen, mach ich
das dennoch. Dazu wollte ich den Timestamp Counter der CPU auslesen,
der ja seit Ewigkeiten invariant ist, d.h. nicht mit dem aktuellen
Takt des Kerns variiert, sondern immer mit dem nominellen Basis-Takt
der CPU läuft. Dazu bräuchte ich aber die absolute Frequenz des Time-
stamp-Counters. Unter Win32 kann man die leicht in einem Unter-Baum
der Registry auslesen der nicht persistent ist, sondern sich so ähnlich
wie das /proc-Dateisystem verhält. Ich hab im Netz nichts gefunden
wo ich den Basis-Takt der CPU aus dem /proc-Dateisystem auslesen kann.
Das wär mir aber am liebsten bzw. ich möchte das nicht messen müssen.
Bei Intel-CPUs lässtz sich der Takt meist aus dem CPUID-String auslesen
bzw. rausparsen bzw, der steht dann immer nach dem @xxxGHz; das fänd
ich aber auch nicht so elegant und auf AMD-CPUs funktioniert das sowieso
nicht.

Jakob Hirsch

unread,
Jun 19, 2023, 11:13:04 AM6/19/23
to
Hm, bisschen her...

On 2023-01-24 14:36, Bonita Montero wrote:
> habe ich das Problem, dass die Items mit hoher Frequenz dort eingefügt
> werden und die Verarbeitungs-Semantik bei den Consumern so minimal ist,
> dass diese auch mit der entsprechend hohen Frequenz abgebommen werden.

Hm, es gibt m.W. dafür auch schlankere Konzepte (lockless P/C queue),
vielleicht macht es das etwas einfacher.

> das dennoch. Dazu wollte ich den Timestamp Counter der CPU auslesen,

direkt?
Dafür gibt es üblicherweise System-Aufrufe, siehe
https://en.wikipedia.org/wiki/Time_Stamp_Counter.
Unter Windows ist das QueryPerformanceCounter und
QueryPerformanceFrequency, unter Linux spuckt dir
clock_gettime(CLOCK_MONOTONIC) direkt die Werte aus (mit clock_getres
könntest du dir auch noch die Auflösung holen).
Und es gibt bestimmt auch genug libs für C++ die das schön in einer
StopWatch-Klasse kapseln...

Bonita Montero

unread,
Jun 21, 2023, 12:35:22 PM6/21/23
to
Am 19.06.2023 um 17:13 schrieb Jakob Hirsch:
> Hm, bisschen her...
>
> On 2023-01-24 14:36, Bonita Montero wrote:
>> habe ich das Problem, dass die Items mit hoher Frequenz dort eingefügt
>> werden und die Verarbeitungs-Semantik bei den Consumern so minimal ist,
>> dass diese auch mit der entsprechend hohen Frequenz abgebommen werden.
>
> Hm, es gibt m.W. dafür auch schlankere Konzepte (lockless P/C queue),
> vielleicht macht es das etwas einfacher.

Lockless queues haben sich nie durchgesetzt weil man die pollen muss,
was ein No-Go ist. Das Problem ist dann halt, dass der Producer auch
weg-schedult werden kann, dass der Consumer sich im Endeffekt dumm
und dämlich pollt bis der wieder mal an der Reihe war.

> Dafür gibt es üblicherweise System-Aufrufe, ...

Erzähl mir mal welche. Unter Windows kann ich den Basis-Takt aus der
Registry auslesen, unter Linux weiß ich nicht wo ich den unter /proc
finden kann. /proc/cpuinfo ist keine zuverlässige Quelle, denn da
findet man das ggf. nur im Prozessor-String.

> Unter Windows ist das QueryPerformanceCounter und
> QueryPerformanceFrequency, ...

Die ist auf x86ern immer 10MHz.

> unter Linux spuckt dir clock_gettime(CLOCK_MONOTONIC) ...

CLOCK_MONOTINIC_RAW bedient sich direkt am TSC.

>direkt die Werte aus (mit clock_getres könntest du dir auch noch die Auflösung
> holen).Und es gibt bestimmt auch genug libs für C++ die das schön in einer
> StopWatch-Klasse kapseln...

Ich hab jetzt mal geschaut wie effizient die Abfrage von
CLOCK_MONOTINIC_RAW auf meinem Linux-Rechner ist (AMD TR 3990X):

#include <iostream>
#include <iomanip>
#include <chrono>
#include <time.h>

using namespace std;
using namespace chrono;

int main()
{
auto start = high_resolution_clock::now();
constexpr uint64_t ROUNDS = 10'000'000;
timespec ts;
for( uint64_t r = ROUNDS; r--; )
clock_gettime( CLOCK_MONOTONIC_RAW, &ts );
double ns = (double)duration_cast<nanoseconds>(
high_resolution_clock::now() - start ).count() / ROUNDS;
cout << ns << endl;
}

Das zieht dann ca. 19ns, damit kann man leben.
0 new messages