当前位置: 首页 > 面试题库 >

gos中有类似memset吗?

苏凯
2023-03-14
问题内容

在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模拟(将数组初始化为一些非零值的快速方法)?


问题答案:

带有循环的最简单的解决方案如下所示:

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

memset标准库中没有支持,但是我们可以使用copy()高度优化的内置函数。

反复 copy()

我们可以手动设置第一个元素,然后使用copy();开始将已设置的部分复制到未设置的部分。每次已经设置的部分越来越大(两倍),因此迭代次数为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])
    }
}

此解决方案的灵感来自的实现bytes.Repeat()。如果只想创建一个[]byte填充相同值的新值,则可以使用该bytes.Repeat()函数。您不能将它用于现有的切片或其他切片[]byte,因为您可以使用呈现的切片memsetRepeat()

如果是小片,memsetRepeat()可能会慢一些memsetLoop()(但如果是小片,这并不重要,它将立即运行)。

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

对这两个解决方案进行基准测试:

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

基准结果

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倍

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

100,000个元素: 快约1.5倍

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

最高的性能提升约为3800-4000个元素, 速度提高了约3.2倍



 类似资料:
  • Gos 自称为 “Armed Golang(加强版的 Go)”,定位是原生 go 命令的一个“加强版”解决方案。 据官方介绍可以使用 gos 代替 go: go get => gos getgo build => gos buildgo run => gos rungo ... => gos ... 因为 gos 兼容所有的 go 命令,并且还额外增加了搭载智能 GOPROXY 的 go mod/

  • gos-log 基于Go语言的轻量级高性能的大日志检索系统 开源地址 gos-log https://gitee.com/dianjiu/gos-log https://github.com/dianjiu/gos-log gos-log-vue https://gitee.com/dianjiu/gos-log-vue https://github.com/dianjiu/gos-log-vue

  • memset(将一段内存空间填入某值) 相关函数 bzero,swab 表头文件 #include<string.h> 定义函数 void * memset (void *s ,int c, size_t n); 函数说明 memset()会将参数s所指的内存区域前n个字节以参数c填入,然后返回指向s的指针。在编写程序时,若需要将某一数组作初始化,memset()会相当方便。 返回值 返回指向s的

  • memset 将一段内存空间填入某值 相关函数 bzero,swab 表头文件 #include<string.h> 定义函数 void *memset(void *s, int c, size_t n); 函数说明 memset()会将参数s所指的内存区域前n个字节以参数c填入,然后返回指向s的指针。在编写程序时,若需要将某一数组作初始化,memset()会相当方便。 返回值 返回指向s的指

  • 问题内容: Java中是否有内置方法来查找任何数据类型的大小?有什么方法可以找到尺寸? 问题答案: 否。标准Java SE类库中没有这种方法。 设计者的观点是Java不需要它,因为该语言使应用程序1无需知道需要为原始值,对象或具有给定数量的元素的数组保留多少空间。 您可能会认为sizeof运算符对需要了解其数据结构占用多少空间的人很有用。但是,您还可以使用Java内存分析器简单,可靠地获得此信息以