有没有类似于memset的内容? [英] Is there analog of memset in go?

查看:118
本文介绍了有没有类似于memset的内容?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在C ++中,我可以使用 memset

  const int MAX = 1000000; 
int is_prime [MAX]

memset(is_prime,1,sizeof(is_prime))

什么memset可以做到,粗略地说可以用一些值来填充数组,但这样做确实非常快。



在我可以做的 is_prime:= make([] int,1000000),但是这将创建一个所有0的片段,类似的方式我可以使用 new [1000000] int),但没有任何东西可以让我创建一个包含所有1或任何其他非零元素的数组/切片。



当然,我可以使用一个循环在后面用值填充它,但是 memset 的主要目的是它比循环快得多。



Go程序员也有一个 memset analog(将数组初始化为某个非零值的快速方法)? b $ b

解决方案

使用循环的最简单解决方案如下所示:

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

没有 memset 支持标准库,但我们可以使用内置的 < code $ copy>() ,这是高度优化的。

重复 copy()



我们可以手动设置第一个元素,并使用 copy()将已设置的部分复制到未设置的部分);已经设置的部分每次都会变得越来越大(双打),所以迭代次数是 log(n)

  func memsetRepeat(a [] int,v int){
如果len(a)== 0 {
return
} $ b对于bp:= 1,$ ba [0] = v
; bp< LEN(一); bp * = 2 {
copy(a [bp:],a [:bp])
}
}

这个解决方案受到 bytes.Repeat () 。如果你只是想创建一个新的 [] byte 填充相同的值,你可以使用 bytes.Repeat() [] byte 之外,您不能将它用于现有切片或切片,因为您可以使用所提供的 memsetRepeat()

如果小片 memsetRepeat()可能比 memsetLoop()(但是如果是小切片,它并不重要,它会立即运行)。



由于如果元素数量增加,使用快速 copy() memsetRepeat()会更快。



对这两种解决方案进行基准比较:

  var a = make([ 1000)//大小将变化

func BenchmarkLoop(b * testing.B){
for i:= 0;我< b.N; i ++ {
memsetLoop(a,10)
}
}

func BenchmarkRepeat(b * testing.B){
for i:= 0;我< b.N; i ++ {
memsetRepeat(a,11)
}
}



基准测试结果



<100>元素:〜1.15倍

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

1,000个元素:〜2.5倍

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

10,000个元素:〜2倍快 P>

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

100,000元:〜1.5倍

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

高hest的性能增益约为3800-4000个元素,其速度快3.2倍。


In C++ I can initialize an array with some value using memset:

const int MAX = 1000000;
int is_prime[MAX]

memset(is_prime, 1, sizeof(is_prime))

What memset does, crudely can be described as filling the array with some value, but doing this really really fast.

In go I can do is_prime := make([]int, 1000000), but this will create a slice with all 0, in the similar manner I can use new([1000000]int), but nothing will allow me to create an array/slice with all 1 or any other non-zero element.

Of course I can use a loop to populate it with the value later, but the main purpose of memset is that it is way way faster than the loop.

So do Go programmers have a memset analog (fast way of initializing array to some non-zero value)?

解决方案

The simplest solution with a loop would look like this:

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

There is no memset support in the standard library, but we can make use of the built-in copy() which is highly optimized.

With repeated copy()

We can set the first element manually, and start copying the already set part to the unset part using copy(); where the already set part gets bigger and bigger every time (doubles), so the number of iterations is 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])
    }
}

This solution was inspired by the implementation of bytes.Repeat(). If you just want to create a new []byte filled with the same values, you can use the bytes.Repeat() function. You can't use that for an existing slice or slices other than []byte, for that you can use the presented memsetRepeat().

In case of small slices memsetRepeat() may be slower than memsetLoop() (but in case of small slices it doesn't really matter, it will run in an instant).

Due to using the fast copy(), memsetRepeat() will be much faster if the number of elements grows.

Benchmarking these 2 solutions:

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)
    }
}

Benchmark results

100 elements: ~1.15 times faster

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

1,000 elements: ~2.5 times faster

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

10,000 elements: ~2 times faster

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

100,000 elements: ~1.5 times faster

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

The highest performance gain is around 3800-4000 elements where it is ~3.2 times faster.

这篇关于有没有类似于memset的内容?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆