Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

474
Visualizações
¿C++ Linux es la forma más rápida de medir el tiempo (más rápido que std::chrono)? Punto de referencia incluido
#include <iostream> #include <chrono> using namespace std; class MyTimer { private: std::chrono::time_point<std::chrono::steady_clock> starter; std::chrono::time_point<std::chrono::steady_clock> ender; public: void startCounter() { starter = std::chrono::steady_clock::now(); } double getCounter() { ender = std::chrono::steady_clock::now(); return double(std::chrono::duration_cast<std::chrono::nanoseconds>(ender - starter).count()) / 1000000; // millisecond output } // timer need to have nanosecond precision int64_t getCounterNs() { return std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::steady_clock::now() - starter).count(); } }; MyTimer timer1, timer2, timerMain; volatile int64_t dummy = 0, res1 = 0, res2 = 0; // time run without any time measure void func0() { dummy++; } // we're trying to measure the cost of startCounter() and getCounterNs(), not "dummy++" void func1() { timer1.startCounter(); dummy++; res1 += timer1.getCounterNs(); } void func2() { // start your counter here dummy++; // res2 += end your counter here } int main() { int i, ntest = 1000 * 1000 * 100; int64_t runtime0, runtime1, runtime2; timerMain.startCounter(); for (i=1; i<=ntest; i++) func0(); runtime0 = timerMain.getCounter(); cout << "Time0 = " << runtime0 << "ms\n"; timerMain.startCounter(); for (i=1; i<=ntest; i++) func1(); runtime1 = timerMain.getCounter(); cout << "Time1 = " << runtime1 << "ms\n"; timerMain.startCounter(); for (i=1; i<=ntest; i++) func2(); runtime2 = timerMain.getCounter(); cout << "Time2 = " << runtime2 << "ms\n"; return 0; }

Estoy tratando de perfilar un programa donde ciertas partes críticas tienen un tiempo de ejecución medido en <50 nanosegundos. Descubrí que mi clase de temporizador que usa std::chrono es demasiado costosa (el código con tiempo toma un 40% más de tiempo que el código sin él). ¿Cómo puedo hacer una clase de temporizador más rápida?

Creo que algunas llamadas al sistema específicas del sistema operativo serían la solución más rápida. La plataforma es Linux Ubuntu.

Editar: todo el código se compila con -O3. Se garantiza que cada temporizador solo se inicialice una vez, por lo que el costo medido se debe únicamente a las funciones startMeasure/stopMeasure. No estoy haciendo ninguna impresión de texto.

Edición 2: la respuesta aceptada no incluye el método para convertir realmente el número de ciclos en nanosegundos. Si alguien puede hacer eso, sería muy útil.

over 4 years ago · Santiago Trujillo
1 Respostas
Responde à pergunta

0

Lo que quieres se llama "micro-benchmarking". Puede volverse muy complejo. Supongo que está usando Ubuntu Linux en x86_64. Esto no es válido para ARM, ARM64 o cualquier otra plataforma.

std::chrono se implementa en libstdc++ (gcc) y libc++ (clang) en Linux como una simple envoltura alrededor de GLIBC, la biblioteca C, que hace todo el trabajo pesado. Si observa std::chrono::steady_clock::now() verá llamadas a clock_gettime().

clock_gettime() es un VDSO, es decir, es un código del núcleo que se ejecuta en el espacio de usuario. Debería ser muy rápido, pero puede ser que de vez en cuando tenga que hacer un poco de limpieza y tarde mucho cada n-ésima llamada. Así que no lo recomendaría para microbenchmarking.

Casi todas las plataformas tienen un contador de ciclos y x86 tiene la instrucción de ensamblaje rdtsc . Esta instrucción se puede insertar en su código creando llamadas asm o usando los componentes integrados específicos del compilador __builtin_ia32_rdtsc() o __rdtsc().

Estas llamadas devolverán un número entero de 64 bits que representa la cantidad de relojes desde que se encendió la máquina. rdtsc no es inmediato sino rápido, tardará entre 15 y 40 ciclos en completarse.

No se garantiza en todas las plataformas que este contador sea el mismo para cada núcleo, así que tenga cuidado cuando el proceso se mueva de un núcleo a otro. Sin embargo, en los sistemas modernos esto no debería ser un problema.

Otro problema con rdtsc es que los compiladores a menudo reordenan las instrucciones si descubren que no tienen efectos secundarios y, lamentablemente, rdtsc es uno de ellos. Por lo tanto, debe usar barreras falsas alrededor de estas lecturas de contador si ve que el compilador le está engañando: observe el ensamblaje generado.

También un gran problema es la propia ejecución fuera de orden de la CPU. No solo el compilador puede cambiar el orden de ejecución, sino también la CPU. Dado que el x86 486, las CPU Intel están canalizadas, por lo que se pueden ejecutar varias instrucciones al mismo tiempo, en términos generales. Entonces podría terminar midiendo la ejecución espuria.

Te recomiendo que te familiarices con los problemas cuánticos del micro-benchmarking. No es sencillo.

Observe que rdtsc() devolverá el número de ciclos. Tienes que convertir a nanosegundos usando la frecuencia del contador de marca de tiempo.

Aquí hay un ejemplo:

 #include <iostream> #include <cstdio> void dosomething() { // yada yada } int main() { double sum = 0; const uint32_t numloops = 100000000; for ( uint32_t j=0; j<numloops; ++j ) { uint64_t t0 = __builtin_ia32_rdtsc(); dosomething(); uint64_t t1 = __builtin_ia32_rdtsc(); uint64_t elapsed = t1-t0; sum += elapsed; } std::cout << "Average:" << sum/numloops << std::endl; }

Este documento está un poco desactualizado (2010), pero está lo suficientemente actualizado como para brindarle una buena introducción al micro-benchmarking:

Cómo comparar tiempos de ejecución de código en arquitecturas de conjuntos de instrucciones Intel® IA-32 e IA-64

over 4 years ago · Santiago Trujillo Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda