在64位计算机上分析Set实现

时间:2009-12-18 02:47:29

标签: c

我系统的相关信息: Core2Duo T6500 gcc(GCC)4.4.1 20090725(Red Hat 4.4.1-2)

使用基本集实现,其中存储的每个集合实际上只是存储集的词典顺序,您可以对Union,Intersection,elementQ等Set操作使用标准位操作。

我的问题是关于确定集合的大小。像Cliquer这样的实现使用

static int set_bit_count[256]

存储任何给定的可能8位字符串中的位数,然后算法将一次通过8位来确定集合的大小。

我有两个问题:

  1. 如果寄存器的速度比缓存或RAM快8倍,则会浪费速度。
  2. 在64位计算机中,int运算速度不比说unsigned long long int慢,我假设它是64位CPU上的标准运算整数。
  3. 但我想象一下只使用一个简单的

    while(x)
      x&=x-1;
      ++count;
    

    可能会更快,因为所有内容都可以存储在寄存器中。但是在不利方面,除了明显的8倍以上的运营之外,还有其他什么呢?

    此外, int, uint, unsigned long, unsigned long long有很多不同的组合,我不知道从哪里开始测试。

    你知道关于这个主题的任何文章吗?

    您是否对此主题有任何其他SO问题?

    你对此有什么见解吗?

    您对如何分析这个有什么建议吗?我从未使用过gprof。当我使用time.h时,我不能比粒度更精细。

    如果你这样做,我将非常感激。

2 个答案:

答案 0 :(得分:1)

最有可能(虽然我现在懒得测试),最快的就是

int popcount(unsigned x) {
    int count;
#if defined(__GNUC__)
    __asm__("popcnt %1,%0" : "=r" (count) : "r" (x));
#elif defined(_MSC_VER)
    __asm {
        POPCNT x, count
    };
#else
    /* blah, who cares */
    for (count = 0; x; count += x&1, x >>= 1);
#endif
    return count;
}

(虽然如果CPU不支持SSE4.2,这会爆炸。)当然,使用编译器的内置内在函数会更好(也更便于移植),一般来说我会相信编译器选择最适合当前目标平台的任何实现。

int popcount(unsigned x);
#if defined(__GNUC__)
# define popcount __builtin_popcount
#elif defined(_MSC_VER)
# define popcount __popcnt
#else
/* fallback implementation */
#fi

答案 1 :(得分:0)

我将使用随机数生成器来分析两种不同的实现来创建位模式。我会循环多次迭代,在每次迭代期间累积一些东西(例如,位计数的异或),我将在循环结束时打印出来。累积和打印是必要的,这样编译器就不会优化任何重要的东西。