如果我有两个包含u8的数组,是否可以将它们转换为更大的整数类型以减少需要做的加法运算数量? 例如,如果两个字节数组每个包含4个字节,我可以将它们每个都变成u32 ,进行加法u32 ,然后将它们转换回吗?

例如:

let a = u32::from_ne_bytes([1, 2, 3, 4]);
let b = u32::from_ne_bytes([5, 6, 7, 8]);

let c = a + b;
let c_bytes = u32::to_ne_bytes(c);

assert_eq!(c_bytes, [6, 8, 10, 12]);

本示例将导致正确的输出。

  1. 这是否总是产生正确的输出(假设没有溢出)?
  2. 这比单独进行添加要快吗?
  3. 其他整数类型是否成立? 如2- u16在A S u32加入2其他u16在A S u32

如果存在并且很常见,那叫什么呢?

#1楼 票数:1 已采纳

  1. 这是否总是产生正确的输出(假设没有溢出)?

是。 如果每个总和小于256,这将根据需要添加字节。 在每种情况下,您都已为本地字节序指定了“ ne”。 不管本机字节序如何,这都将起作用,因为操作是按字节进行的。

如果您编写了代码以实际检查总和是否在范围内,那么几乎可以肯定会撤消所获得的任何额外的提速(如果有的话)。

  1. 这比单独进行添加要快吗?

也许。 唯一确定的唯一方法是测试。

  1. 其他整数类型是否成立? 如2- u16在A S u32加入2其他u16在A S u32

是的,但是您需要注意字节顺序。

如果存在并且很常见,那叫什么呢?

这并不常见,因为通常是不必要的。 这种类型的优化使代码更难阅读,并引入了相当大的复杂性和出现错误的机会。 当您的代码保持可读性和可维护性时,Rust编译器和它们之间的LLVM能够找到您从未想到的极其复杂的优化。

如果有名称,则为SIMD,并且大多数现代处理器都原生支持其形式(SSE,MMX,AVX)。 您可以使用内置功能手动执行此操作,例如core::arch::x86_64::_mm_add_epi8 ,但是LLVM可能会自动执行。 尝试手动执行此操作可能会干扰LLVM可能进行的优化,同时使您的代码更易于出错。


无论如何,我都不是汇编代码方面的专家,但是我研究了为以下两个函数生成汇编

#[no_mangle]
#[inline(never)]
pub fn f1(a1: u8, b1: u8, c1: u8, d1: u8, a2: u8, b2: u8, c2: u8, d2: u8) -> [u8; 4]{
    let a = u32::from_le_bytes([a1, b1, c1, d1]);
    let b = u32::from_le_bytes([a2, b2, c2, d2]);
    u32::to_le_bytes(a + b)
}

#[no_mangle]
#[inline(never)]
pub fn f2(a1: u8, b1: u8, c1: u8, d1: u8, a2: u8, b2: u8, c2: u8, d2: u8) -> [u8; 4]{
    [a1 + a2, b1 + b2, c1 + c2, d1 + d2]
}

f1的汇编:

movzx r10d, byte ptr [rsp + 8]
shl ecx, 24
movzx eax, dl
shl eax, 16
movzx edx, sil
shl edx, 8
movzx esi, dil
or esi, edx
or esi, eax
or esi, ecx
mov ecx, dword ptr [rsp + 16]
shl ecx, 24
shl r10d, 16
movzx edx, r9b
shl edx, 8
movzx eax, r8b
or eax, edx
or eax, r10d
or eax, ecx
add eax, esi
ret

对于f2

add r8b, dil
add r9b, sil
add dl, byte ptr [rsp + 8]
add cl, byte ptr [rsp + 16]
movzx ecx, cl
shl ecx, 24
movzx edx, dl
shl edx, 16
movzx esi, r9b
shl esi, 8
movzx eax, r8b
or eax, esi
or eax, edx
or eax, ecx
ret

较少的指令并不一定会使它更快,但这并不是一个坏的指导原则。


经过仔细的测量和测试后,将这种优化视为最后的选择。

  ask by kyle translate from so

未解决问题?本站智能推荐:

1回复

编译器是否优化数学表达式?

rustc 会优化这些表达式吗? 2*x -> x<<1 x/2 -> x>>1 x % 8 -> x&7 而这样的
1回复

我可以在Rust中按值有效地返回对象吗?

我想用一个函数初始化一个大对象。 目前我有: 我希望拥有: 我听说C ++通常会实现返回值优化(RVO),如果您幸运的话,并且具有良好的编译器。 我们可以在这里禁用复制,并通过传递给函数的隐藏指针将其返回吗? RVO是语言的一部分还是可选的优化?
1回复

标准库中是否有任何函数可以返回两个数字中的较大或较小值?

我可以使用以下代码自行实现: 我自己实施它是多余的。
2回复

是否可以在 Rust 中获得整数的本机 CPU 大小?

为了好玩,我正在用 Rust 编写一个 bignum 库。 我的目标(与大多数 bignum 库一样)是尽可能提高效率。 我希望它即使在不寻常的架构上也能高效。 在我看来,CPU 将在具有架构的本机位数的整数上更快地执行算术运算(即 64 位机器的u64位机器的u16等)因此,因为我想创建一个在所
1回复

如何创建一个Rust类型,可以容纳单个单词大小内的整数或指针?

(我指的是装箱作为一种在运行时区分整数和指针的方法。一种技术使用了一些编程语言来辅助GC(例如OCaml) ,而不是Rust Box<T>类型。) 我有一个Rust枚举看起来像这样: #[derive(Clone, Copy, Debug, PartialEq)] enum
2回复

对64位整数进行按位运算的成本是否与8位整数相同?

我的代码涉及对庞大的整数数组进行按位运算。 如果理解正确,则64位计算机将在一个时钟周期内对64位整数进行计算。 如果我正在执行8位整数按位运算,它仍然会消耗1个时钟周期。 如果我执行8个8位整数运算,则将消耗8个时钟周期。 知道我可以将8个8位整数放入一个64位整数中,并对64位整数进
1回复

有没有比收敛泰勒级数更有效的方法来分治 64 位硬件上的 uint 256 日志?

我希望将 256 位无符号整数的对数基数 n(10 可以)作为 Rust 中的浮点,而不会损失精度。 在我看来,我需要实现一个 8xf64 512 位浮点 512 类型并使用泰勒级数来近似 ln 然后是对数。 我知道有一些汇编方法可以获取 f64 的日志。 我想知道堆栈溢出是否有人能想到分而治之或其
1回复

Rust:如何向 u8 数组添加一个

我正在 AES 以 CTR 模式工作以进行学习,并且需要在最后向 ctr 块添加“一个”。 但是为了添加一个,我必须将先前代码的结果(返回 [u8;16] 的 aes_encryption)转换为 u128。 现在我想将此 u128 转换回数组。 有没有可能这样做? 我的另一种想法是使用std::c