es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

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>

Tags:  , , , ,

Answer

  1. Avatar for 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 a write.

    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.

    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é 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 buffer b, una variable oc atomic de tipo unsigned long long y cuando está definido THR, también declara dos semáforos s. 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 cuando THR está definido.

    En el bucle, el programa mide el tiempo de ejecución utilizando la función rdtscp() y suma la diferencia a oc. Después de ciertas instancias del bucle, imprime la suma de los ciclos de reloj entre mediciones a través de la función fprintf(). Cuando está definido THR, la función write() 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 a write() 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.

Comments are closed.