4

好的,我想要的很简单:

  • 设置数字的第 N 位(= 设为“1”)
  • 取消设置数字的第 N 位(= 将其设为“0”)

到目前为止,这是我的代码(以 2 个宏的形式):

#define SETBIT(X,Y)     X|=(1ULL<<(Y))
#define UNSETBIT(X,Y)   X&=(~(1ULL<<(Y)))

他们都工作正常。事情是 :

  • 有什么可以优化的吗?
  • 它可以做得更快吗?

(这两个操作都应该每秒执行数百万次,因此性能至关重要)。

4

4 回答 4

6

您可以通过摆脱宏来稍微加快编译时间,但仅此而已。位旋转足够快,所以它不应该是一个问题。

这是惯用的做法,我不会改变任何事情。

于 2012-12-30T16:04:54.267 回答
3

这是在 C 中设置和清除位的标准方法。

如果您想潜在地加速这些宏,您可以查看这些操作的 Linux 汇编实现。

例如,对于x86

http://lxr.linux.no/linux/arch/x86/include/asm/bitops.h

查找__clear_bit__set_bit内联函数。

于 2012-12-30T16:11:17.223 回答
2

这些宏是最佳惯用的,因此如果需要进行优化,编译器可能会识别这些表达式。

您可能获得的唯一加速是......如果有更好的选择,请避免使用它们。如果您经常执行相同的多位操作(例如,打开位 0、2 和 4),您可以通过使用单个而不是使用多个SETBITs 来执行所有这些操作来获得一些好处。

于 2012-12-30T16:08:21.657 回答
2

首先,您应该将宏修复为:

#define SETBIT(X,Y)     ( (X) |= 1ULL << (Y) )
#define UNSETBIT(X,Y)   ( (X) &= ~(1ULL << (Y)) ) )

这样代码就像SETBIT(a, 2) + 1;预期的那样工作,并且SETBIT(1+a, 2);会按预期产生错误。

你可能永远不会那样使用宏,但是额外的括号是免费的,解决与宏相关的问题可能是这样的 PITA,它总是把额外的()或放在{}宏周围。

补充:使用内联汇编和 CPU 位旋转操作,并假设Y在编译时未知,UNSETBIT 可以更快,避免 NOT... 伪代码:

X = X OR (0xFFFFFFFFFFFFFFFE ROL Y)

然后,尽管这些宏尽可能高效(C 编译器应将它们优化为理想的汇编指令),但您或许应该提供宏来操作多个位,例如:

#define SET2BITS(X, B1, B2)     ( (X) |= 1ULL << (B1) | 1ULL << (B2) )

在某些情况下,使用内部表达式的类似函数的宏可能更有效(尽管编译器优化可能会获得相同的最终结果):

#define BITSETVAL(X, B)     ( (X) | 1ULL << (B) )
于 2012-12-30T16:56:44.960 回答