utilizar utiliza sirve que para code array go slice memset

utiliza - ¿Hay análogo de memset en ir?



para que se utiliza memset en c (2)

De acuerdo con este error titulado "optimice memset idiom" no hay forma de hacer esto en Go que no sea con un bucle. El tema fue cerrado el 9 de enero de 2013 con esta publicación.

Considero esto arreglado. La optimización de casos no nulos no es muy interesante.

Podemos abrir otro error si la gente siente fuertemente por hacer más.

Así que la solución es usar un bucle ya cubierto por icza.

Hay bytes.Repeat() pero eso también usa un bucle:

func Repeat(b []byte, count int) []byte { nb := make([]byte, len(b)*count) bp := copy(nb, b) for bp < len(nb) { copy(nb[bp:], nb[:bp]) bp *= 2 } return nb }

En C ++ puedo inicializar una matriz con algún valor usando memset :

const int MAX = 1000000; int is_prime[MAX] memset(is_prime, 1, sizeof(is_prime))

Lo que hace memset, crudamente puede describirse como que llena la matriz con algún valor, pero hacerlo realmente muy rápido.

In go puedo hacer is_prime := make([]int, 1000000) , pero esto creará una porción con todo 0, de la misma manera puedo usar new([1000000]int) , pero nada me permitirá crear una array / slice con todos 1 o cualquier otro elemento distinto de cero.

Por supuesto, puedo usar un bucle para poblarlo con el valor más adelante, pero el propósito principal de memset es que es mucho más rápido que el bucle.

Entonces, ¿los programadores de Go tienen un memset analógico (forma rápida de inicializar la matriz a un valor distinto de cero)?


La solución más simple con un bucle se vería así:

func memsetLoop(a []int, v int) { for i := range a { a[i] = v } }

No hay soporte de memset en la biblioteca estándar, pero podemos hacer uso de la copy() integrada copy() que está altamente optimizada.

Con copy() repetida copy()

Podemos configurar el primer elemento manualmente y comenzar a copiar la parte ya establecida en la parte no configurada usando copy() ; donde la parte ya establecida se hace más y más grande cada vez (se duplica), por lo que el número de iteraciones es log(n) :

func memsetRepeat(a []int, v int) { if len(a) == 0 { return } a[0] = v for bp := 1; bp < len(a); bp *= 2 { copy(a[bp:], a[:bp]) } }

Esta solución se inspiró en la implementación de bytes.Repeat() . bytes.Repeat() . Si solo desea crear un nuevo []byte con los mismos valores, puede usar la función bytes.Repeat() . No puede usar eso para un segmento o memsetRepeat() existentes que no sean el []byte , para eso puede usar el memsetRepeat() .

En el caso de pequeños segmentos, memsetRepeat() puede ser más lento que memsetLoop() (pero en el caso de pequeños cortes, realmente no importa, se ejecutará en un instante).

Debido al uso de la copy() rápida copy() , memsetRepeat() será mucho más rápido si el número de elementos aumenta.

Benchmarking estas 2 soluciones:

var a = make([]int, 1000) // Size will vary func BenchmarkLoop(b *testing.B) { for i := 0; i < b.N; i++ { memsetLoop(a, 10) } } func BenchmarkRepeat(b *testing.B) { for i := 0; i < b.N; i++ { memsetRepeat(a, 11) } }

Resultados de referencia

100 elementos: ~ 1.15 veces más rápido

BenchmarkLoop 20000000 81.6 ns/op BenchmarkRepeat 20000000 71.0 ns/op

1.000 elementos: ~ 2.5 veces más rápido

BenchmarkLoop 2000000 706 ns/op BenchmarkRepeat 5000000 279 ns/op

10,000 elementos: ~ 2 veces más rápido

BenchmarkLoop 200000 7029 ns/op BenchmarkRepeat 500000 3544 ns/op

100,000 elementos: ~ 1.5 veces más rápido

BenchmarkLoop 20000 70671 ns/op BenchmarkRepeat 30000 45213 ns/op

La mayor ganancia de rendimiento es de alrededor de 3800-4000 elementos, donde es ~ 3.2 veces más rápido .