Last active
July 23, 2023 14:20
-
-
Save datenwolf/151486f6d73c9b25ac701bdbdef373a5 to your computer and use it in GitHub Desktop.
Online RDTSC visualisation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <GL/glut.h> | |
#include <imgui.h> | |
#include <imgui_impl_glut.h> | |
#include <imgui_impl_opengl2.h> | |
#include <sched.h> | |
#include <math.h> | |
#include <stdio.h> | |
#include <x86intrin.h> | |
#include <time.h> | |
static double timespec_to_double(timespec const &t) | |
{ return t.tv_sec + t.tv_nsec*1e-9; } | |
static void measure_rdtsc( | |
float &rdtsc_mean, float &rdtsc_var, | |
float &clock_mean, float &clock_var ) | |
{ | |
timespec start, end; | |
double mean, M2; | |
double clocks[10] = {}; | |
uint64_t tscs[1000] = {}; | |
for( unsigned j = 0; j < 10; ++j ){ | |
sched_yield(); | |
clock_gettime(CLOCK_MONOTONIC_RAW, &start); | |
for( unsigned i = 0; i < 100; ++i ){ | |
tscs[j*100+i] = __rdtsc(); | |
} | |
clock_gettime(CLOCK_MONOTONIC_RAW, &end); | |
clocks[j] = (timespec_to_double(end) - timespec_to_double(start))*1e6; // to us | |
} | |
mean = M2 = 0; | |
for( unsigned i = 1; i < 1000; ++i ){ | |
double diff = tscs[i] - tscs[i-1]; | |
double const delta = diff - mean; | |
mean += delta/i; | |
double const Delta = diff - mean; | |
M2 += delta * Delta; | |
} | |
rdtsc_mean = mean; rdtsc_var = M2/1000; | |
mean = M2 = 0; | |
for( unsigned i = 1; i <= 10; ++i ){ | |
double diff = clocks[i-1]; | |
double const delta = diff - mean; | |
mean += delta/i; | |
double const Delta = diff - mean; | |
M2 += delta * Delta; | |
} | |
clock_mean = mean; clock_var = M2/10; | |
} | |
static unsigned rdtsc_measure_i = 0; | |
static float rdtsc_clock_ratio_mean[1024], rdtsc_clock_ratio_stddev[1024]; | |
static void display() | |
{ | |
// Start the Dear ImGui frame | |
ImGui_ImplOpenGL2_NewFrame(); | |
ImGui_ImplGLUT_NewFrame(); | |
auto const w = ImGui::GetContentRegionAvailWidth(); | |
ImGui::Text("looped RDTSC/Clock ratio delta"); | |
ImGui::PlotLines("##rdtsc clock ratio", rdtsc_clock_ratio_mean, 1024, | |
0, NULL, 0, 200, ImVec2(w, 256) ); | |
ImGui::Text("looped RDTSC/Clock stddev"); | |
ImGui::PlotLines("##rdtsc clock ratio stddev", rdtsc_clock_ratio_stddev, 1024, | |
0, NULL, 0, 20, ImVec2(w, 64) ); | |
// Rendering | |
ImGui::Render(); | |
ImGuiIO& io = ImGui::GetIO(); | |
glViewport(0, 0, (GLsizei)io.DisplaySize.x, (GLsizei)io.DisplaySize.y); | |
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); | |
//glUseProgram(0); // You may want this if using this code in an OpenGL 3+ context where shaders may be bound, but prefer using the GL2 code. | |
ImGui_ImplOpenGL2_RenderDrawData(ImGui::GetDrawData()); | |
glutSwapBuffers(); | |
} | |
static void idle() | |
{ | |
float rdtsc_mean, rdtsc_var, clock_mean, clock_var; | |
measure_rdtsc(rdtsc_mean, rdtsc_var, clock_mean, clock_var); | |
rdtsc_clock_ratio_mean [rdtsc_measure_i] = rdtsc_mean/clock_mean; | |
rdtsc_clock_ratio_stddev[rdtsc_measure_i] = pow(rdtsc_var*clock_var, 0.25); | |
rdtsc_measure_i = (rdtsc_measure_i + 1) % 1024; | |
glutPostRedisplay(); | |
} | |
int main( int argc, char *argv[] ) | |
{ | |
glutInit( &argc, argv ); | |
glutInitDisplayMode( GLUT_RGBA | GLUT_DOUBLE ); | |
glutCreateWindow( "RDTSC Measure" ); | |
glutDisplayFunc( display ); | |
// Setup Dear ImGui context | |
IMGUI_CHECKVERSION(); | |
ImGui::CreateContext(); | |
ImGuiIO& io = ImGui::GetIO(); (void)io; | |
// Setup Platform/Renderer bindings | |
ImGui_ImplGLUT_Init(); | |
ImGui_ImplGLUT_InstallFuncs(); | |
ImGui_ImplOpenGL2_Init(); | |
glutIdleFunc(idle); | |
glutMainLoop(); | |
// Cleanup | |
ImGui_ImplOpenGL2_Shutdown(); | |
ImGui_ImplGLUT_Shutdown(); | |
ImGui::DestroyContext(); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment