duangu1868 2015-06-03 08:00
浏览 120
已采纳

gos中有类似memset吗?

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

  • 写回答

2条回答 默认 最新

  • doutu3352 2015-06-03 08:22
    关注

    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.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥15 使用ue5插件narrative时如何切换关卡也保存叙事任务记录
  • ¥20 软件测试决策法疑问求解答
  • ¥15 win11 23H2删除推荐的项目,支持注册表等
  • ¥15 matlab 用yalmip搭建模型,cplex求解,线性化处理的方法
  • ¥15 qt6.6.3 基于百度云的语音识别 不会改
  • ¥15 关于#目标检测#的问题:大概就是类似后台自动检测某下架商品的库存,在他监测到该商品上架并且可以购买的瞬间点击立即购买下单
  • ¥15 神经网络怎么把隐含层变量融合到损失函数中?
  • ¥15 lingo18勾选global solver求解使用的算法
  • ¥15 全部备份安卓app数据包括密码,可以复制到另一手机上运行
  • ¥20 测距传感器数据手册i2c