Esta pregunta, aunque bastante antigua, necesita algunos puntos de referencia, ya que no pide la forma más idiomática, ni la forma en que se puede escribir en el menor número de líneas, sino la forma más rápida. Y es una tontería responder esa pregunta sin algunas pruebas reales. Así que comparé cuatro soluciones, memset versus std :: fill versus CERO de la respuesta de AnT versus una solución que hice usando intrínsecos AVX.
Tenga en cuenta que esta solución no es genérica, solo funciona con datos de 32 o 64 bits. Por favor comente si este código está haciendo algo incorrecto.
#include<immintrin.h>
#define intrin_ZERO(a,n){\
size_t x = 0;\
const size_t inc = 32 / sizeof(*(a));/*size of 256 bit register over size of variable*/\
for (;x < n-inc;x+=inc)\
_mm256_storeu_ps((float *)((a)+x),_mm256_setzero_ps());\
if(4 == sizeof(*(a))){\
switch(n-x){\
case 3:\
(a)[x] = 0;x++;\
case 2:\
_mm_storeu_ps((float *)((a)+x),_mm_setzero_ps());break;\
case 1:\
(a)[x] = 0;\
break;\
case 0:\
break;\
};\
}\
else if(8 == sizeof(*(a))){\
switch(n-x){\
case 7:\
(a)[x] = 0;x++;\
case 6:\
(a)[x] = 0;x++;\
case 5:\
(a)[x] = 0;x++;\
case 4:\
_mm_storeu_ps((float *)((a)+x),_mm_setzero_ps());break;\
case 3:\
(a)[x] = 0;x++;\
case 2:\
((long long *)(a))[x] = 0;break;\
case 1:\
(a)[x] = 0;\
break;\
case 0:\
break;\
};\
}\
}
No afirmaré que este es el método más rápido, ya que no soy un experto en optimización de bajo nivel. Más bien es un ejemplo de una implementación dependiente de la arquitectura correcta que es más rápida que Memset.
Ahora, sobre los resultados. Calculé el rendimiento para matrices de tamaño 100 int y long long, asignadas tanto estática como dinámicamente, pero con la excepción de msvc, que eliminó el código muerto en matrices estáticas, los resultados fueron extremadamente comparables, por lo que mostraré solo el rendimiento de matriz dinámica. Las marcas de tiempo son ms para 1 millón de iteraciones, utilizando la función de reloj de baja precisión de time.h.
clang 3.8 (Usando la interfaz clang-cl, indicadores de optimización = / OX / arch: AVX / Oi / Ot)
int:
memset: 99
fill: 97
ZERO: 98
intrin_ZERO: 90
long long:
memset: 285
fill: 286
ZERO: 285
intrin_ZERO: 188
gcc 5.1.0 (indicadores de optimización: -O3 -march = native -mtune = native -mavx):
int:
memset: 268
fill: 268
ZERO: 268
intrin_ZERO: 91
long long:
memset: 402
fill: 399
ZERO: 400
intrin_ZERO: 185
msvc 2015 (indicadores de optimización: / OX / arch: AVX / Oi / Ot):
int
memset: 196
fill: 613
ZERO: 221
intrin_ZERO: 95
long long:
memset: 273
fill: 559
ZERO: 376
intrin_ZERO: 188
Hay muchas cosas interesantes sucediendo aquí: llvm matando a gcc, las típicas optimizaciones irregulares de MSVC (hace una eliminación impresionante de código muerto en matrices estáticas y luego tiene un rendimiento terrible para el relleno). Aunque mi implementación es significativamente más rápida, esto puede deberse solo a que reconoce que el borrado de bits tiene mucho menos sobrecarga que cualquier otra operación de configuración.
La implementación de Clang merece más atención, ya que es significativamente más rápida. Algunas pruebas adicionales muestran que su conjunto de memorias está de hecho especializado para memsets de cero o distintos de cero para una matriz de 400 bytes que son mucho más lentos (~ 220ms) y son comparables a los de gcc. Sin embargo, la configuración de memoria distinta de cero con una matriz de 800 bytes no hace ninguna diferencia de velocidad, lo que probablemente sea la razón por la que en ese caso, su configuración de memoria tiene un rendimiento peor que mi implementación: la especialización es solo para matrices pequeñas y el límite es de alrededor de 800 bytes. También tenga en cuenta que gcc 'fill' y 'ZERO' no optimizan memset (mirando el código generado), gcc simplemente está generando código con características de rendimiento idénticas.
Conclusión: memset no está realmente optimizado para esta tarea tan bien como la gente pretendería (de lo contrario, gcc, msvc y memset de llvm tendrían el mismo rendimiento). Si el rendimiento importa, entonces Memset no debería ser una solución final, especialmente para estos arreglos de tamaño medio incómodos, porque no está especializado en la eliminación de bits y no está optimizado a mano mejor que el compilador por sí solo.
new
es C ++ ...