2010-10-21 14 views
7

Tengo una pregunta sobre la velocidad de desreferenciación del puntero. Tengo una estructura como esta:Velocidad de desreferenciación del puntero de estructura C

typedef struct _TD_RECT TD_RECT; 
struct _TD_RECT { 
    double left; 
    double top; 
    double right; 
    double bottom; 
}; 

Mi pregunta es, ¿cuál de estos sería más rápido y por qué?


CASO 1:

TD_RECT *pRect; 
... 
for(i = 0; i < m; i++) 
{ 
    if(p[i].x < pRect->left) ... 
    if(p[i].x > pRect->right) ... 
    if(p[i].y < pRect->top) ... 
    if(p[i].y > pRect->bottom) ... 
} 

CASO 2:

TD_RECT *pRect; 
double left = pRect->left; 
double top = pRect->top; 
double right = pRect->right; 
double bottom = pRect->bottom; 
... 
for(i = 0; i < m; i++) 
{ 
    if(p[i].x < left) ... 
    if(p[i].x > right) ... 
    if(p[i].y < top) ... 
    if(p[i].y > bottom) ... 
} 

Así en el caso 1, el bucle se dereferencing directamente el puntero pRect para obtener la comparación valores. En el caso 2, se hicieron nuevos valores en el espacio local de la función (en la pila) y los valores se copiaron del pRect a las variables locales. A través de un bucle habrá muchas comparaciones.

En mi mente, serían igualmente lento, ya que la variable local es también una referencia a memoria en la pila, pero no estoy seguro ...

Además, sería mejor mantener referencia p [] por índice, o incrementar p por un elemento y desreferenciarlo directamente sin un índice.

¿Alguna idea? Gracias :)

+13

Deje de perder su tiempo con la optimización prematura que probablemente no hará una gran diferencia. –

+1

tal vez importa la fracción de un smidge, pero si lo hace, ¿por qué no medirlo? – kenny

+0

Para Win32, ¿podría usar GetTickCount() para medir el tiempo antes y después de llamar al ciclo para medir la velocidad, o hay una forma mejor? – oldSkool

Respuesta

1

Creo que el segundo caso es probable que sea más rápido porque no está desreferenciando el puntero a pRect en cada iteración de bucle.

Prácticamente, un compilador que realiza la optimización puede notar esto y puede que no haya diferencia en el código que se genera, pero la posibilidad de que pRect sea un alias de un elemento en p [] podría evitarlo.

12

Probablemente descubrirá que no hará la diferencia con los compiladores modernos. La mayoría de ellos probablemente realizaría una eliminación de subexpresiones común de las expresiones que no cambian dentro del ciclo. No es prudente suponer que hay un mapeo simple uno a uno entre sus declaraciones C y el código ensamblador. He visto un código de bomba de gcc que avergonzaría mis habilidades como ensamblador.

Pero esta no es una pregunta en C ni en C++ ya que el estándar ISO no ordena cómo se hace. La mejor manera de verificarlo con seguridad es generar el código de ensamblador con algo como gcc -S y examinar los dos casos en detalle.

También obtendrá un mayor retorno de su inversión si se aleja de este tipo de micro-optimización y se concentra más en el nivel macro, como la selección de algoritmos y tal.

Y, como con todas las preguntas de optimización, medida, ¡no adivine! Existen demasiadas variables que pueden afectarlo, por lo que debe comparar diferentes enfoques en el entorno objetivo y con datos realistas.

+0

Pregunto porque la función que estoy escribiendo está recortando polígonos para mapas vectoriales que contienen millones de vértices ... cualquier cantidad de velocidad que pueda extraer me ayudará porque necesito recortar cada sección en áreas de 1 grado. – oldSkool

+2

Eso está bien. Lo correcto es ejecutar los puntos de referencia del mundo real ya que depende de una gran cantidad de factores, muy pocos de los cuales conocemos. Como mínimo, su máquina de destino, el compilador, la CPU, otros problemas arquitectónicos como la memoria y los subsistemas de E/S, la composición de sus datos, el nivel de optimización, etc. – paxdiablo

+0

Que tienes millones de ellos, mira mi comentario a continuación. Crea un índice en tu mapa vectorial (¿es p?), Ordenado por x y por y. (¿Sigue siendo bastante estático?). O clasifíquelo en x y tenga un índice en y. Use la búsqueda binaria para encontrar todo x right, all y bottom. Entonces, si usted dice que 4 millones son 22 comparaciones para cada uno, 88 en total, ¡en lugar de los 16 millones que tiene ahora! – CashCow

0

Un compilador de optimización verá que los accesos a la estructura son invariantes de bucle y también un Loop-invariant code motion, haciendo que sus dos casos se vean iguales.

3

No es probable que sea una gran diferencia de rendimiento crítico. Podría hacer un perfil de cada opción varias veces y ver. Asegúrese de tener sus optimizaciones de compilador establecidas en la prueba.

Con respecto al almacenamiento de los dobles, es posible que obtenga algún rendimiento al usar const. ¿Qué tan grande es tu matriz?

Con respecto al uso de la aritmética del puntero, esto puede ser más rápido, sí.

Puede optimizar al instante si conoce < a la derecha en su rect (seguramente debe ser). Si x < se fue, tampoco puede ser> correcto para que pueda poner en "else".

Su gran optimización, si hay una, vendría de no tener que recorrer todos los elementos de su matriz y no tener que realizar 4 comprobaciones en todos ellos.

Por ejemplo, si indizaste o clasificaste tu matriz en xey, podrías, usando la búsqueda binaria, encontrar todos los valores que tienen x < a la izquierda y recorrer esos solo.

0

Me sorprenderé si incluso una compilación totalmente no optimizada (- O0) producirá differentcode para los dos casos presentados. Para realizar cualquier operación en un procesador moderno, los datos deben cargarse en los registros. Por lo tanto, incluso cuando declare variables automáticas, estas variables no existirán en la memoria principal, sino en uno de los procesadores de coma flotante. Esto será cierto incluso cuando no declare las variables usted mismo y, por lo tanto, no espero que exista diferencia en el código máquina generado, incluso cuando declare las variables temporales en su código C++.

Pero como han dicho otros, compile el código en el ensamblador y compruébelo usted mismo.

Cuestiones relacionadas