Recuerde que este
for (i = 0; i < sizeof(my_buffer); i++)
{
p[i] = 0;
}
también puede ser más rápido que
for (i = 0; i < sizeof(my_buffer); i++)
{
*p++ = 0;
}
Como ya se ha contestado, el compilador a menudo ha optimizado la mano rutinas f o memset() memcpy() y otras funciones de cadena. Y estamos hablando significativamente más rápido. ahora la cantidad de código, número de instrucciones, que un fast memcpy o memset del compilador, es generalmente mucho más grande que la solución de bucle que sugirió. menos líneas de código, menos instrucciones no significan más rápido.
De todos modos, mi mensaje es probar ambos. diagrame el código, vea la diferencia, intente comprender, haga preguntas en el desbordamiento de la pila si no lo hace. y luego use un temporizador y cronometra las dos soluciones, llame a cualquiera de las funciones de memcpy miles o cientos de miles de veces y tiempo todo (para eliminar el error en el tiempo). Asegúrese de hacer copias cortas como digamos 7 elementos o 5 elementos, y copias grandes como cientos de bytes por memset y pruebe algunos números primos mientras está en ello. En algunos procesadores de algunos sistemas, su ciclo puede ser más rápido para algunos elementos, como 3 o 5, o algo así, muy rápidamente, aunque se vuelve lento.
Aquí hay una pista sobre el rendimiento. La memoria DDR en su computadora tiene 64 bits de ancho y necesita escribirse 64 bits a la vez, quizás tiene ecc y debe calcular a través de esos bits y escribir 72 bits a la vez. No siempre es ese número exacto, pero síguelo, tendrá sentido para 32 bits o 64 o 128 o lo que sea. Si realiza una instrucción de escritura de byte único para ejecutar ram, el hardware necesitará hacer una de estas dos cosas, si no hay cachés en el camino, el sistema de memoria debe realizar una lectura de 64 bits, modificar el byte y luego escríbelo. Sin algún tipo de optimización de hardware, escribir 8 bytes dentro de esa fila de una copita, es de 16 ciclos de memoria, y dram es muy muy lento, no te dejes engañar por los números de 1333mhz.
Ahora, si tiene una memoria caché, la primera escritura de bytes va a requerir una línea de caché leída de dram, que es una o varias de estas lecturas de 64 bits, las próximas 7 o 15 o cualquier escritura de byte probablemente vaya a sea realmente rápido, ya que solo van a la caché y no a ddr, eventualmente esa línea de caché se apaga, dramáticamente, una o dos o cuatro, etc. de estos 64 bits o cualquier ubicación de ddr. Así que, aunque solo está escribiendo, todavía tiene que leer todo el ram y escribirlo, por lo tanto, el doble de ciclos que desee. Si es posible, y es con algunos procesadores y sistemas de memoria, el memset o la parte de escritura de una memcpy, pueden ser instrucciones individuales con una línea de caché completa o una ubicación ddr completa y no se requiere lectura, la velocidad duplicada al instante.Esta no es la forma en que funcionan todas las optimizaciones, pero con suerte le da una idea de cómo pensar sobre el problema. Con su programa siendo arrastrado a la memoria caché en las líneas de caché, puede duplicar o triplicar la cantidad de instrucciones ejecutadas si, a cambio, obtiene la mitad o un trimestre o más recortes en el número de ciclos de DDR y gana en general.
Como mínimo, las rutinas memset y memcpy del compilador van a realizar una operación de bytes si la dirección de inicio es impar, entonces un 16 bit si no está alineado en 32 bits. Luego, un 32 bit si no está alineado en 64 y en adelante hasta que alcancen el tamaño de transferencia óptimo para ese conjunto de instrucciones/sistema. En el brazo tienden a apuntar a 128 bits. Entonces, el peor de los casos en la parte frontal sería un byte único, luego una palabra y luego unas pocas palabras, luego ingrese al conjunto principal o al ciclo de copia. En el caso de las transferencias ARM de 128 bits, se escribieron 128 bits por instrucción. Luego en la parte de atrás si no se alinea el mismo trato, unas pocas palabras, una mitad de palabra, un byte y el peor de los casos. También verá que las bibliotecas hacen cosas como, si el número de bytes es menor que X donde X es un número pequeño como 13 o más, entonces entra en un bucle como el suyo, simplemente copie algunos bytes debido a la cantidad de instrucciones y ciclos de reloj para apoyar ese ciclo es más pequeño/más rápido. Desmontar o encontrar el código fuente de gcc para ARM y probablemente mips y algunos otros buenos procesadores y ver de lo que estoy hablando.
Si 'p' va a apuntar a los objetos de tipo' struct My_Buffer_Type', por favor indíquelo de esa manera, en lugar de darle un tipo diferente y abarrotar el código con moldes innecesarios. – sarnold
también considera la inicialización: 'struct My_Buffer_Type my_buffer [5] = {0};' recursivamente inicializa todo en (el tipo correcto de) '0'. – pmg
@sarnold Gracias por el consejo. Estaba tratando de simplificar un buffer mucho más complicado para el ejemplo. –