【问题标题】:bitwise - how are the bitmasks operations implemented?按位 - 位掩码操作是如何实现的?
【发布时间】:2014-10-31 16:24:41
【问题描述】:

上下文

我使用了很多按位运算,但我什至不知道它们是如何在最低级别实现的。

我想看看英特尔/AMD 开发人员如何实现此类操作。不在我的代码中替换它们,那将是愚蠢的。但是要更广泛地了解正在发生的事情。

我试图找到一些信息,但大多数时候,人们会询问它的用途或将其替换为其他按位运算,但这里并非如此。

问题

它是否在 32 位的程序集(sse)中进行基本迭代并进行比较?

是否有一些技巧可以加快速度?

谢谢

【问题讨论】:

  • 位运算是原始运算;有组装说明来做。因此,它们是在 CPU 上的逻辑门中实现的,而不是代码。
  • a = b & c; 这样的代码行可能有一条直接的机器级指令或两条可以做到这一点 - 不太可能有任何技巧来加快速度。

标签: c assembly bitmask


【解决方案1】:

大多数都直接在 CPU 上实现,作为基本的本机指令,而不是 SSE 的一部分。这些是 CPU 寄存器上最古老、最基本的操作。

至于andorxor等是如何实现的,如果你真的感兴趣,可以去看看数字逻辑设计,或者离散数学。查找触发器、AND 门或 NAND / NOR / XOR 门

https://en.wikipedia.org/wiki/NAND_logic

还可以查找 K-maps(卡诺图),您可以使用这些来手动实现逻辑电路。

https://en.wikipedia.org/wiki/Karnaugh_map

如果您真的喜欢阅读,如果您可以进入工程或计算机科学大学,则可以报名参加数字逻辑设计课程。您将在面包板上使用大型 IC 构建逻辑电路,但现在大多数 CPU 都是用代码(如软件)“编写”的,并“打印”在硅片上。

特别感兴趣的是NANDNOR,因为它们的功能完整(您可以使用 NAND 或 NOR 构造任何真值表)。

NAND(逻辑符号看起来像=Do-)

A
  =Do- Q    is Q = NOT(A AND B)
B

Truth table
A    B     Q
0    0     1
0    1     1
1    0     1
1    1     0

你可以用 NAND 重写任何逻辑。

您也可以看到,它非常高效,您无法获得比具有二进制的单个门更低的级别(尽管存在三元/三态逻辑),因此它是单个时钟状态更改。因此,对于一个 64 位 CPU 寄存器,您需要并排放置 64 个这些婴儿,每个寄存器...每个内核...每个指令。那只是“逻辑”寄存器。因为高级处理器(如 Intel Core)会进行寄存器重命名,所以硅中的物理寄存器比逻辑上可用的名称要多。

【讨论】:

  • NOR 在功能上也是完整的,NAND 也是如此。
  • +1 用于添加对数字逻辑和 k-maps 的引用
  • 谢谢大家,我修改并添加了 NOR,还添加了一点 ASCII 艺术!如果您对 NAND 或 NOR 更好的 ASCII 代表有建议,请告诉我。
  • 如果处理器的物理寄存器比逻辑寄存器多得多,为什么不公开所有物理寄存器。我的意思是,如果我们有 16 个逻辑寄存器并说 100 个物理寄存器,为什么我们不能直接访问(而不是间接)这 100 个物理寄存器?
  • @Zboson - 我没有说“更多”的物理寄存器,你说了。它只是“超标量”的一个方面。这可能意味着处理器有一些额外的(储备)或两个。它用于代码的乱序执行、推测和并行化,而无需您(或编译器)显式编写操作来实现它。它们没有被公开的原因是(1)寄存器现在是真正的逻辑/虚拟概念,(2)如果它们被公开,人们会使用它们并破坏或干扰自动超标量设施。
【解决方案2】:

AND、OR、XOR 和 NOT 操作在硅片中非常有效地实现,因此在大多数处理器上通常是单周期本机指令。也就是说,对于一个 16 位处理器,整个 16 位寄存器是一次与运算;在 32 位处理器上,一次 32 位等。您可能需要注意的唯一性能问题是 对齐:在 ARM 处理器上,例如,如果 32 位值开始如果内存地址是 4 的倍数,则读取-修改-写入可以在两个或三个周期内完成。如果它在一个奇数地址,它必须在相邻的对齐地址进行两次读取和两次写入,因此速度较慢。

在一些较旧的处理器中,移位可能涉及循环单次移位。也就是说,1 << 5 将比1 << 2 花费更长的时间。但是大多数现代处理器都有一个所谓的“桶形移位器”,它可以将所有移位均衡到寄存器大小,所以在 Pentium 上,1 << 31 花费的时间不会超过1 << 2

加法和减法也是快速原语。乘法和除法很棘手:它们大多是作为微码循环实现的。乘法可以通过在高端处理器中将循环展开成巨大的硅片来加速,但除法不能,因此通常除法是微处理器中最慢的基本操作。

【讨论】:

  • +1 用于桶形移位器和对齐。这实际上就是我们必须关心代码对齐的原因。
【解决方案3】:

按位运算是处理器的组成部分,因此使用指令公开这些运算是很自然的。 AND、OR、XOR、NOR、NAND 和 NOT 等运算可以由 ALU 执行,每位只需几个逻辑门。重要的是,结果的每一位只依赖于输入的两位(与乘法或加法不同),因此整个运算可以并行进行,没有任何复杂性。

【讨论】:

    【解决方案4】:

    如您所知,计算机中的数据以二进制格式表示。

    例如,如果您有整数 13,则它表示为 1101b(其中 b 表示二进制)。这适用于(1) * 8 + (1) * 4 + (0) * 2 + (1) * 1 = 13,就像(1) * 10 + (3) * 1 = 13——不同的基础。

    但是,对于基本操作,计算机需要知道您正在处理多少数据。典型的整数大小是 32 位。所以它不仅仅是1101b,它是00000000000000000000000000001101b——32位,其中大部分未使用。

    按位操作就是这样——它们只在位级别上操作。加法、乘法和其他操作一次考虑多个位来执行它们的功能,但按位运算符不考虑。例如:

    12 位加 7 是什么? (C语言,12 & 7

    1010b 12 &
    0111b  7
    -----  =
    0010n  2
    

    为什么?垂直思考!看看左边的一组数字——1和0是0。然后,0和1是0。然后,1和1是1。最后,0和1是0。

    这是基于陈述这些规则的 and 真值表——只有真(又名 1)和真(又名 1)才会导致假(又名 0)。所有其他结果值都是假的(又名 0)。

    同样,or 真值表表明所有结果都是真(又名 1),但假(又名 0)和假(又名 0)导致假(又名 0)。

    让我们做同样的例子,但这次让我们计算 12 按位或 7。(或者在 C 语言中,12 | 7

    1010b 12 |
    0111b  7
    -----  =
    1111n 15
    

    最后,让我们考虑另一个主要的位运算符:不是。这是一个一元运算符,您只需翻转每一位。让我们按位计算而不是 7(或用 C 语言,~7

    0111b ~7
    -----  =
    1000b  8
    

    但是等等……那些前导零呢?嗯,是的,在我因为它们不重要而忽略它们之前,但现在它们肯定是:

    00000000000000000000000000000111b ~7
    ---------------------------------  =
    11111111111111111111111111111000b  ... big number?
    

    如果您指示计算机将结果视为无符号整数(32 位),那么这是一个非常大的数字。 (略少于 40 亿)。如果您指示计算机将结果视为有符号整数(32 位),则为 -8。

    正如您可能已经猜到的那样,由于所有这些操作的逻辑非常简单,因此您无法单独使它们更快。但是,按位运算遵循与布尔逻辑相同的逻辑,因此您可以使用布尔逻辑缩减技术来减少您可能需要的按位运算的数量。

    例如(A & B) | (A & C) 结果与A & (B | C) 相同

    但是,这是一个更大的话题。卡诺图是一种技术,但boolean algebra 通常是我在编程时最终使用的。

    【讨论】:

    • 回想起来,我可能误读了这个问题,但我会把它留在这里,以防它对某人有用。
    猜你喜欢
    • 1970-01-01
    • 2021-03-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-06-29
    • 1970-01-01
    • 2021-05-29
    相关资源
    最近更新 更多