将字节打包到u32与将它们存储在vec<u8>中的性能差异?

介绍:

我很好奇将小数存储为位打包无符号整数与字节向量的性能差异(cpu 和内存使用量)

例子

我将使用存储 RGBA 值的示例。它们是 4 个字节,因此很容易将它们存储为u32.
但是,将它们存储为类型的向量会更具可读性u8

作为一个更详细的例子,假设我想存储和检索颜色 rgba(255,0,0,255)

这就是我将如何去做这两种方法:

// Bitpacked:
let i: u32 = 4278190335;
//binary is 11111111 00000000 00000000 11111111
//In reality I would most likely do something more similar to:
let i: u32 = 255 << 24 + 255; //i think this syntax is right

// Vector:
let v: Vec<u8> = [255,0,0,255];

然后可以查询这两个红色值

i >> 24 
//or
&v[0]
//both expressions evaluate to 255 (i think. I'm really new to rust <3 )

问题 1

据我所知, 的值v必须存储在堆上,因此存在与此相关的性能成本。这些成本是否足以使位包装值得?

问题2

然后是两个表达式i >> 24&v[0]。我不知道 Rust 在位移位与从堆中获取值的速度有多快。我会测试它,但我暂时无法访问安装了 Rust 的机器。有人可以立即了解这两种操作的缺点吗?

问题 3

最后,内存使用的差异是否就像仅在堆栈上存储 32 位u32用于指针v与在堆栈上存储 64 位用于指针以及在堆上存储32 位的值一样简单v

对不起,如果这个问题有点混乱

回答

使用 aVec会更贵;正如您提到的,它将需要执行堆分配,并且访问也将进行边界检查。

也就是说,如果您改用数组[u8; 4],则与位打包u32表示相比的性能应该几乎相同。

实际上,请考虑以下简单示例:

pub fn get_red_bitpacked(i: u32) -> u8 {
    (i >> 24) as u8
}

pub fn get_red_array(v: [u8; 4]) -> u8 {
    v[3]
}

pub fn test_bits(colour: u8) -> u8 {
    let colour = colour as u32;
    let i = (colour << 24) + colour;
    get_red_bitpacked(i)
}

pub fn test_arr(colour: u8) -> u8 {
    let v = [colour, 0, 0, colour];
    get_red_array(v)
}

我查看了Compiler Explorer,编译器决定了这一点,get_red_bitpacked并且get_red_array完全相同:以至于它甚至没有为前者生成代码。这两个“测试”功能显然也针对完全相同的程序集进行了优化。

example::get_red_array:
        mov     eax, edi
        shr     eax, 24
        ret

example::test_bits:
        mov     eax, edi
        ret

example::test_arr:
        mov     eax, edi
        ret

显然这个例子被编译器看穿了:为了进行适当的比较,你应该用实际代码进行基准测试。也就是说,我觉得相当有把握地说,使用 Rust ,这些操作的u32vs性能[u8; 4]通常应该是相同的。


以上是将字节打包到u32与将它们存储在vec&lt;u8&gt;中的性能差异?的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>