Al observar la salida del ensamblaje, gcc en realidad desenrolla este bucle para usar los registros mmx para volcar en 16 bytes a la vez hasta que se acerca al final. Yo diría que es bastante rápido. La versión de memset salta a memset, que supongo que es casi tan rápida. Yo usaría tu método.
Omnifarioso
Pero, saltar a memset es una sola instrucción, por lo que su uso dará como resultado un tamaño binario más pequeño.
Alexander Shishenko
2
esto no es exactamente lo que solicitó OP, pero simplemente reasignar su vector a uno nuevo del mismo tamaño ( v = std::vector<int>(vec_size,0)) parece un poco más rápido que fillen mi máquina
Yibo Yang
1
Esta es la forma más idiomática de hacerlo, más idiomática que usarla assign.
alfC
1
¿Asignarlo a un nuevo vector hace la asignación del montón? y luego descartar la asignación del vector existente? Pude ver que es más lento que memset et al.
Conrad Jones
150
Como siempre cuando preguntas sobre el más rápido: ¡Mide! Usando los métodos anteriores (en una Mac usando Clang):
usando 100000 iteraciones en un vector de 10000 ints.
Editar: si el cambio de estos números cambia de manera plausible los tiempos resultantes, puede tener cierta confianza (no tan buena como la inspección del código de ensamblaje final) de que el punto de referencia artificial no se ha optimizado por completo. Por supuesto, lo mejor es ensuciar el rendimiento en condiciones reales.
fin Editar
+1. Este punto de referencia en particular no es concluyente, pero el punto es absolutamente correcto, debe escribir una prueba de rendimiento de las alternativas, ya que realmente se utilizarán. Si no hay una diferencia de rendimiento, utilice la fuente más simple.
Steve Jessop el
3
"... no es concluyente ..." OMI, esta falta de conclusión en sí misma ya es un buen punto para hacer puntos de referencia, la mayoría de las veces el Optimizer ya hace un muy buen trabajo para el tipo de situaciones sobre las que el OP preguntó. Y modificaría su última oración para leer "Si no hay una diferencia de rendimiento significativa ..."
Además, wow, si le importa la velocidad sin optimizaciones (lo que podría ser plausible si está implementando en modo 'depuración', lo que hacen algunos equipos), se fillve terrible. Es dos órdenes de magnitud más lento en esta prueba.
Kyle Strand
55
@KyleStrand: No es que el relleno sea terrible, es una plantilla y el código se genera con -O0 dentro de su unidad de traducción. Cuando usa memset, está usando el código libc que se compiló con -O3 (incluso cuando compila su código con -O0). Si le importa la velocidad en la depuración y usa plantillas, tendrá que usar una instanciación de plantilla explícita en un archivo separado que compile con -O3
Dado que el estándar (2003 TC1) garantiza que un vector std :: es contiguo en la memoria, esto debería estar bien. Si su biblioteca de c ++ no se ajusta al TC1 2003, entonces no use esto.
Mario
2
@ Mario: No habría publicado esto a menos que fuera cierto y se supusiera que era conocido, por supuesto. :) Pero gracias.
Descansa el
1
Revisé la asamblea. El ::std::fillmétodo se expande a algo que es bastante rápido, aunque un poco en el lado del código, ya que todo está en línea. Sin embargo, todavía lo usaría porque es mucho más agradable de leer.
Omnifarioso
44
Será mejor que agregue verificar si el vector está vacío y no hacer nada en este caso. Calcular & buf [0] para un vector vacío puede generar aserciones en el código STL.
Sergey
4
tratar
std::fill
y también
std::size siz = vec.size();//no memory allocating
vec.resize(0);
vec.resize(siz,0);
Tenía la misma pregunta pero bastante corta vector<bool>(afaik el estándar permite implementarlo internamente de manera diferente que solo una matriz continua de elementos booleanos). Por lo tanto, repetí las pruebas ligeramente modificadas de Fabio Fracassi. Los resultados son los siguientes (tiempos, en segundos):
-O0 -O3
----------------
memset 0.6661.045
fill 19.3571.066iterator67.3681.043
assign 17.9750.530for i 22.6101.004
Entonces, aparentemente para estos tamaños, vector<bool>::assign()es más rápido. El código utilizado para las pruebas:
Respuestas:
fuente
v = std::vector<int>(vec_size,0)
) parece un poco más rápido quefill
en mi máquinaassign
.Como siempre cuando preguntas sobre el más rápido: ¡Mide! Usando los métodos anteriores (en una Mac usando Clang):
usando 100000 iteraciones en un vector de 10000 ints.
Editar: si el cambio de estos números cambia de manera plausible los tiempos resultantes, puede tener cierta confianza (no tan buena como la inspección del código de ensamblaje final) de que el punto de referencia artificial no se ha optimizado por completo. Por supuesto, lo mejor es ensuciar el rendimiento en condiciones reales. fin Editar
para referencia el código usado:
Conclusión: ¡ uso
std::fill
(porque, como otros han dicho, es lo más idiomático)!fuente
assign
es más lento, excepto para pequeñas capacidades enlibc++
. CÓDIGO coliru / pastefill
ve terrible. Es dos órdenes de magnitud más lento en esta prueba.¿Qué hay de la
assign
función miembro?fuente
Si es solo un vector de enteros, primero probaría:
No es muy C ++, así que estoy seguro de que alguien proporcionará la forma adecuada de hacerlo. :)
fuente
::std::fill
método se expande a algo que es bastante rápido, aunque un poco en el lado del código, ya que todo está en línea. Sin embargo, todavía lo usaría porque es mucho más agradable de leer.tratar
y también
fuente
Tenía la misma pregunta pero bastante corta
vector<bool>
(afaik el estándar permite implementarlo internamente de manera diferente que solo una matriz continua de elementos booleanos). Por lo tanto, repetí las pruebas ligeramente modificadas de Fabio Fracassi. Los resultados son los siguientes (tiempos, en segundos):Entonces, aparentemente para estos tamaños,
vector<bool>::assign()
es más rápido. El código utilizado para las pruebas:Usé el compilador GCC 7.2.0 en Ubuntu 17.10. La línea de comando para compilar:
fuente