Skip to content

Instantly share code, notes, and snippets.

@datenwolf
Last active July 23, 2023 14:20
Show Gist options
  • Save datenwolf/151486f6d73c9b25ac701bdbdef373a5 to your computer and use it in GitHub Desktop.
Save datenwolf/151486f6d73c9b25ac701bdbdef373a5 to your computer and use it in GitHub Desktop.
Online RDTSC visualisation
#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