La llamada al sistema “syscall” se vuelve considerablemente más lenta cuando es invocada desde otro hilo.
Si defines THR
, el código realizará el mismo trabajo pero en otro hilo. Solo medí el tiempo empleado en la llamada a write
.
Al ejecutar el código con ./nombre-del-archivo >/dev/null
, este es el resultado que obtengo, que son los ciclos de reloj acumulados.
THR
no definido
1 48930106
2 43946464
3 44669126
4 45918011
5 44108477
6 43608789
7 45104427
8 49676889
9 44682305
10 47516931
THR
definido
1 108347418
2 101670307
3 101726085
4 100531554
5 100137343
6 85837022
7 105556754
8 104681843
9 110303338
10 104666783
¿Por qué es mucho más lento el write
cuando se llama desde otro hilo?
El sistema es Fedora Linux.
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include <semaphore.h>
#include <fcntl.h>
#include <unistd.h>
#include <immintrin.h>
#ifdef __cplusplus
#include <atomic>
using namespace std;
#else
#include <stdatomic.h>
#endif
#define SIZE 0x100000
static unsigned long long rdtscp() {
unsigned _;
return __rdtscp(&_);
}
static char b[SIZE];
static atomic_ullong oc;
#ifdef THR
static sem_t s[2];
void *out(void *_) {
for (;;) {
sem_wait(s);
unsigned long long c = rdtscp();
write(1, b, SIZE);
oc += rdtscp() - c;
sem_post(s + 1);
}
return _;
}
#endif
int main() {
memset(b, 'a', SIZE);
#ifdef THR
sem_init(s, false, 0);
sem_init(s + 1, false, 0);
pthread_t t;
pthread_create(&t, NULL, out, NULL);
#endif
for (int i = 1;; ++i) {
#ifdef THR
sem_post(s);
sem_wait(s + 1);
#else
unsigned long long c = rdtscp();
write(1, b, SIZE);
oc += rdtscp() - c;
#endif
const int d = 100000;
if (!(i % d)) {
unsigned long long _oc = atomic_exchange(&oc, 0);
fprintf(stderr, "%4d%12llu\n", i / d, _oc);
}
}
}
No estoy seguro si esto está bien, pero hice que el código pueda compilarse en C y C++ para agregar la etiqueta de C++. Si no es apropiado, volveré atrás.</stdatomic.h></immintrin.h></unistd.h></fcntl.h></semaphore.h></pthread.h></string.h></stdio.h></stdbool.h>
davy.ai
Explicación de los Resultados del Código
Pregunta
Si defines
THR
, el código hará el mismo trabajo pero en otro hilo. Solo medí el tiempo invertido en la llamada awrite
.Al ejecutar el código con
./some-file-name>/dev/null
, este es el resultado que obtengo, que es la acumulación de ciclos de reloj.¿Por qué
write
es mucho más lento cuando se llama desde otro hilo?El sistema es Fedora Linux.
Explicación
Este código en C/C++ mide el tiempo que se tarda en ejecutar la llamada
write()
para escribir en la salida estándar. Declara un bufferb
, una variableoc
atomic de tipo unsigned long long y cuando está definidoTHR
, también declara dos semáfoross
. El programa inicializa el buffer y ejecuta un bucle infinito. Luego, ya sea escribe directamente en la salida estándar o señala un semáforo cuandoTHR
está definido.En el bucle, el programa mide el tiempo de ejecución utilizando la función
rdtscp()
y suma la diferencia aoc
. Después de ciertas instancias del bucle, imprime la suma de los ciclos de reloj entre mediciones a través de la funciónfprintf()
. Cuando está definidoTHR
, la funciónwrite()
es más lenta, acumulando más ciclos de reloj antes de imprimir que cuando no está definida.La explicación más probable de por qué
write()
es más lento cuando se llama desde otro hilo es el cambio de contexto a nivel del sistema operativo. Escribir en un archivo generalmente se considera una operación costosa. Al llamar awrite()
desde múltiples hilos, existe la posibilidad de cambios de contexto para coordinar el acceso al sistema de archivos, lo que conlleva una sobrecarga y un tiempo de ejecución más lento.