以下是在x86-64上设置C中的单个位的两种方法:
inline void SetBitC(long *array, int bit) {
//Pure C version
*array |= 1<<bit;
}
inline void SetBitASM(long *array, int bit) {
// Using inline x86 assembly
asm("bts %1,%0" : "+r" (*array) : "g" (bit));
}
Run Code Online (Sandbox Code Playgroud)
使用带有-O3 -march=core2选项的GCC 4.3,与常量一起使用时,C版本需要大约90%的时间bit.(两个版本编译为完全相同的汇编代码,但C版本使用or [1<<num],%rax指令而不是bts [num],%rax指令)
与变量一起使用时bit,C版本表现更好,但仍然明显慢于内联汇编.
重置,切换和检查位具有类似的结果.
为什么GCC对这种常见操作的优化程度如此之差?我是否在使用C版本做错了什么?
编辑:对不起,等待漫长的等待,这是我用来进行基准测试的代码.它实际上是一个简单的编程问题...
int main() {
// Get the sum of all integers from 1 to 2^28 with bit 11 always set
unsigned long i,j,c=0;
for …Run Code Online (Sandbox Code Playgroud) 我想使用bts和bt x86汇编指令来加速Mac上C++代码中的位操作.在Windows上,_bittestandset和_bittest内在函数运行良好,并提供显着的性能提升.在Mac上,gcc编译器似乎不支持这些,所以我试图直接在汇编程序中执行它.
这是我的C++代码(注意'bit'可以> = 32):
typedef unsigned long LongWord;
#define DivLongWord(w) ((unsigned)w >> 5)
#define ModLongWord(w) ((unsigned)w & (32-1))
inline void SetBit(LongWord array[], const int bit)
{
array[DivLongWord(bit)] |= 1 << ModLongWord(bit);
}
inline bool TestBit(const LongWord array[], const int bit)
{
return (array[DivLongWord(bit)] & (1 << ModLongWord(bit))) != 0;
}
Run Code Online (Sandbox Code Playgroud)
以下汇编程序代码可以工作,但不是最优的,因为编译器无法优化寄存器分配:
inline void SetBit(LongWord* array, const int bit)
{
__asm {
mov eax, bit
mov ecx, array
bts [ecx], eax
}
}
Run Code Online (Sandbox Code Playgroud)
问题:如何使编译器完全优化bts指令?如何用bt指令替换TestBit?
我知道位字段是依赖于编译器的,但是我没有在最新的g ++和Visual C++ 2010上找到关于位字段的线程安全性的文档.
位字段成员的操作是原子的吗?