Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

429
Vistas
C/C++: qué es más rápido: un bucle for o incrementar un puntero

Me pregunto cuál de los siguientes segmentos de código sería el más rápido, suponiendo que el objetivo es leer de los elementos de tipo T en cantidad numElements señalados por somePointer y hacer algo con ellos. Estoy específicamente interesado en la eficiencia de la estructura de bucle en sí, no en lo que se hace con los elementos.

1er candidato

 for (int i = 0; i < numElements; i++) { T val = somePointer[i]; ... // Do something }

2do candidato

 T* tempPointer = somePointer; T* endPointer = somePointer + numElements; while (tempPointer < endPointer) { T val = *tempPointer; ... // Do something tempPointer++; }

Ciertamente, el primer candidato es más claro y menos propenso a errores. Sin embargo, si realmente se compila en el código que parece que generaría, creo que sería más lento. El uso de un bucle for requiere un incremento de i en cada iteración del bucle, así como un desplazamiento de la dirección a la que apunta somePointer por la cantidad i * sizeOf(t) antes de eliminar la referencia. El método de incremento del puntero parece requerir solo una operación de suma para cada ciclo de ciclo, lo que me lleva a creer que sería más rápido.

Sin embargo, según tengo entendido, los compiladores intentan vectorizar for bucles lo más posible con las instrucciones SIMD; si el compilador puede detectar con éxito una oportunidad para la vectorización en un bucle for pero no for punteros incrementales, entonces parecería ser la opción más rápida. Por supuesto, por lo que sé, el compilador detecta casos en los que los bucles for se pueden convertir en incrementos de puntero y realiza la conversión antes de la vectorización, lo que lo haría irrelevante.

En resumen, en escenarios del mundo real, ¿cuál es más rápido?

over 4 years ago · Santiago Trujillo
3 Respuestas
Responde la pregunta

0

Teóricamente, la respuesta a su pregunta es el código anterior, más simple.

Una implementación real no necesita evaluar parte de una expresión si puede deducir que su valor no se usa y que no se producen efectos secundarios necesarios (incluidos los causados por llamar a una función o acceder a un objeto volátil).

Esta es una cita del estándar C que demuestra el poder otorgado al compilador para realizar optimizaciones. En este caso, las partes de la expresión que no se necesitan están relacionadas con el índice int (que probablemente debería ser size_t ).

De manera realista, la respuesta a su pregunta también es el código anterior, más simple. Es posible que se sorprenda gratamente al descubrir que los compiladores comunes de hoy en día pueden realizar optimizaciones como la que menciona (y aún más compleja) con bastante facilidad . Sin embargo, debido a los muchos aspectos de los sistemas informáticos que se combinan para crear una imagen más amplia del rendimiento, no es posible dar una respuesta sobre cuál de estos será más rápido... Necesitaríamos conocer todos los aspectos relevantes de su implementación. (CPU, memoria, sistema operativo, compilador, etc.).

Consulte "¿Se optimizará?" , para ver algunos ejemplos similares que gcc felizmente optimiza. Esta es una forma de optimización de cálculo invariante de bucle . Asegúrese de compilar su código con optimizaciones completas habilitadas ( -O3 , típicamente).

Sin embargo, no es solo la optimización lo que debe considerar. Como ha mencionado, el código anterior, más simple, es más fácil de leer. Esto es importante para cualquiera que pueda terminar manteniendo su código.

Al considerar la optimización, aquí hay una sugerencia útil: su jefe querrá ver algo que funcione, incluso si es demasiado lento, más temprano que tarde. Si no tienes un jefe, ¡genial! Tenga en cuenta que no puede medir el código optimizado sin tener algo con lo que compararlo, sin embargo...

Escriba un código claro y conciso con el propósito de mantenerlo. Si su jefe (o su equipo, o usted mismo, o lo que sea) decide que no es lo suficientemente rápido cuando está completo, use su generador de perfiles para determinar dónde están los cuellos de botella más importantes, entonces debería tener una idea de en qué concentrarse... Estarás optimizando tu tiempo y tu código.

Una vez que haya completado una optimización, use su generador de perfiles nuevamente para determinar si fue o no una optimización efectiva. De esta manera eliminas el efecto negativo que podrían tener tus conjeturas.

Los compiladores comunes de hoy a menudo pueden incluso realizar optimizaciones basadas en la salida de un generador de perfiles. Esta técnica se llama "optimización guiada por perfiles" y podría valer la pena investigarla...

over 4 years ago · Santiago Trujillo Denunciar

0

Como regla general, el peor tiempo de ejecución de un bucle for, y también de un bucle while como este, es O(n). Dicho esto, crecerá linealmente según la cantidad de elementos que tenga.

En este caso, tiene muy poco valor considerar cuál es más rápido, ya que son esencialmente lo mismo, asumiendo que lo que hará bajo

 //Do something

es el mismo.

Al considerar la eficiencia de su programa, vale la pena considerar tanto el tiempo de ejecución como la eficiencia de la memoria.

Creo que lo que está escrito dentro de su ciclo for/while es de mayor importancia de lo que está afectando su tiempo de ejecución.

¡Espero que esto ayude!

over 4 years ago · Santiago Trujillo Denunciar

0

Suponiendo que está utilizando GCC o MinGW o Cygwin en placas Intel. For loop ha incorporado soporte en las placas de Intel para incrementar el contador ahora si considera el segundo bucle en ese caso, el puntero debe incrementarse con el tamaño del tipo de datos al que apunta, lo que le pedirá al compilador que coloque más código en el ensamblado y eventualmente aumentará los gastos generales de la CPU aumentando más ciclos de CPU para completar su código, pero en el primer caso, el compilador generará un código ensamblador para mantener la variable de contador i en el registro, lo que facilita que la CPU compare y continúe/interrumpa el ciclo. .Si escribe ambos códigos en dos archivos (uno.c y dos.c dicen) y ejecuta el siguiente comando

 gcc -S one.c gcc -S two.c

para ver el código de ensamblaje y si entiende el ensamblaje x86, probablemente pueda entender más claramente lo que quiero decir. Entiendo que el primer ciclo funcionará más rápido si profundiza en cómo funcionan la CPU y el ensamblaje.

over 4 years ago · Santiago Trujillo Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda