golang快速替代memcpy的方法

huangapple go评论89阅读模式
英文:

golang fast alternative to memcpy

问题

我有一个C语言的示例代码:

#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>

int main()
{
    uint32_t dest[4];
    uint8_t src[16] = {0x11, 0x12, 0x13, 0x14,
                       0x22, 0x22, 0x22, 0x22,
                       0x33, 0x33, 0x33, 0x33,
                       0x44, 0x44, 0x44, 0x44};

    memcpy(dest, src, sizeof(src));

    printf("%04X %04X %04X %04X\n", dest[0], dest[1], dest[2], dest[3]);
    return 0;
}

我正在将其迁移到Go语言,我不想使用C.memcpy,并且正在寻找一个快速的替代方法。这是我的代码:

package main

import (
    "fmt"
    "encoding/binary"
)

func main() {
    dest := make([]uint32, 16)
    var src = []byte{0x11, 0x12, 0x13, 0x14,
                     0x22, 0x22, 0x22, 0x22,
                     0x33, 0x33, 0x33, 0x33,
                     0x44, 0x44, 0x44, 0x44}

    dest[0] = binary.LittleEndian.Uint32(src[0:4])
    dest[1] = binary.LittleEndian.Uint32(src[4:8])
    dest[2] = binary.LittleEndian.Uint32(src[8:12])
    dest[3] = binary.LittleEndian.Uint32(src[12:16])

    fmt.Printf("%04X %04X %04X %04X\n", dest[0], dest[1], dest[2], dest[3])
}

我可以使用单个指令将字节数组转换为uint32数组,而不使用C.memcpy吗?我尝试使用copy函数,但出现错误。我知道我可以使用以下指令:

C.memcpy(unsafe.Pointer(&dest[0]), unsafe.Pointer(&src[0]), 16)

我想知道是否存在有效的替代方法。

英文:

I have this example in C

#include &lt;stdlib.h&gt;
#include &lt;stdio.h&gt;
#include &lt;stdint.h&gt;
#include &lt;string.h&gt;

int main()
{
    uint32_t dest[4];
    uint8_t src[16] = {0x11, 0x12, 0x13, 0x14,
                       0x22, 0x22, 0x22, 0x22,
                       0x33, 0x33, 0x33, 0x33,
                       0x44, 0x44, 0x44, 0x44};
 
    memcpy(dest, src, sizeof(src));

    printf(&quot;%04X %04X %04X %04X\n&quot;, dest[0], dest[1], dest[2], dest[3]);
    return 0;
}

and I'm migrating to golang, I don't want use C.memcpy and I'm searching for a fast alternative. This is my code

package main

import (
    &quot;fmt&quot;
    &quot;encoding/binary&quot;
)

func main() {
    dest := make([]uint32, 16)
    var src = []byte{0x11, 0x12, 0x13, 0x14,
                     0x22, 0x22, 0x22, 0x22,
                     0x33, 0x33, 0x33, 0x33,
                     0x44, 0x44, 0x44, 0x44}

    dest[0] = binary.LittleEndian.Uint32(src[0:4])
    dest[1] = binary.LittleEndian.Uint32(src[4:8])
    dest[2] = binary.LittleEndian.Uint32(src[8:12])
    dest[3] = binary.LittleEndian.Uint32(src[12:16])

    fmt.Printf(&quot;%04X %04X %04X %04X\n&quot;, dest[0], dest[1], dest[2], dest[3])
}

Can I convert an array of byte in array of uint32 with a single instruction without use C.memcpy? I tried to use copy but give error.
I know I can use this istruction

C.memcpy(unsafe.Pointer(&amp;dest[0]), unsafe.Pointer(&amp;src[0]), 16)

I'd like to understand if exist a valid alternative

答案1

得分: 7

unsafe.Pointer是绕过Go类型系统的方法,使用unsafe时需要注意一些问题。要获得memcpy的等效操作,你可以将dest切片传递给copy函数,示例如下:https://play.golang.org/p/MFJjHhDZatl

copy(unsafe.Slice((*byte)(unsafe.Pointer(&dest[0])), len(src)), src)

然而,我仍然建议运行一些基准测试,以确保你的使用场景实际上从这种优化中受益。大多数情况下,使用更安全的方法不会对性能产生明显影响。

英文:

unsafe.Pointer is the way to bypass the Go type system, with all the caveats of using the unsafe package. To get the equivalent of memcpy, you would pass your dest slice to copy like so: https://play.golang.org/p/MFJjHhDZatl

copy(unsafe.Slice((*byte)(unsafe.Pointer(&amp;dest[0])), len(src)), src)

However, I would still make sure to run some benchmarks to ensure that your use case actually benefits from this type of optimization. Most situations can use safer methods without noticeable impact on performance.

huangapple
  • 本文由 发表于 2021年11月3日 04:51:52
  • 转载请务必保留本文链接:https://go.coder-hub.com/69816793.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定