Блог пользователя Madiyar

Автор Madiyar, 10 лет назад, По-английски

While solving Andrew Stankevich Contest 32, Problem K, I noticed that __builtin_popcount for long long doesn't work properly, I spent a lot of time to find my mistake, but when I wrote __builtin_popcount by myself it accepted.

__builtin_popcount defined only for int?

  • Проголосовать: нравится
  • +31
  • Проголосовать: не нравится

»
10 лет назад, # |
  Проголосовать: нравится +83 Проголосовать: не нравится
  • __builtin_popcount = int
  • __builtin_popcountl = long int
  • __builtin_popcountll = long long
»
10 лет назад, # |
Rev. 2   Проголосовать: нравится -18 Проголосовать: не нравится

What is " __builtin_popcount"? I found something. But I couldn't find all of them :(

  • »
    »
    10 лет назад, # ^ |
      Проголосовать: нравится +6 Проголосовать: не нравится

    Funny — I could. http://lmgtfy.com/?q=popcount

    About the 3rd result from the top says "popcount returns the number of non-zero bits in x".

    • »
      »
      »
      10 лет назад, # ^ |
        Проголосовать: нравится -9 Проголосовать: не нравится

      It is easy to find what popcount do. But I couldn't find complexity, C++ or C++11, parameters, and works for any compiler? Also I couldn't find it on cplusplus.com .

      • »
        »
        »
        »
        10 лет назад, # ^ |
          Проголосовать: нравится +19 Проголосовать: не нравится

        Okay, you just said you couldn't find anything.

        • »
          »
          »
          »
          »
          10 лет назад, # ^ |
            Проголосовать: нравится 0 Проголосовать: не нравится

          I changed my reply. But still I don't know "complexity, C++ or C++11, parameters, and works for any compiler?"...

»
10 лет назад, # |
Rev. 3   Проголосовать: нравится +22 Проголосовать: не нравится

__builtin_popcount(x) is a function in C++ returns the number of 1-bits set in an int x. In fact, "popcount" stands for "population count," so this is a function to determine how "populated" an integer is.

For example, say we have an int x with value equal to 12. 12 in binary is just 1100, and the rest of the digits are just 0's. So, __builtin_popcount(12) = 2.

»
10 лет назад, # |
Rev. 2   Проголосовать: нравится +12 Проголосовать: не нравится

Interesting fact : __builtin_popcount is slow. Can anyone tell the complexity? For a constant time bitcount use this : http://pastie.org/9412225 .Please don't ask me how it works exactly! It'd be useful to add it to your library code :)

  • »
    »
    10 лет назад, # ^ |
      Проголосовать: нравится +5 Проголосовать: не нравится

    Is __builtin_popcount slow too much? Or only little?

    • »
      »
      »
      10 лет назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится

      I don't know. Maybe you can tell me :)

    • »
      »
      »
      10 лет назад, # ^ |
        Проголосовать: нравится +2 Проголосовать: не нравится

      Seems that it is the fastest way to count bits in c++ in general case.

      • »
        »
        »
        »
        8 лет назад, # ^ |
          Проголосовать: нравится +36 Проголосовать: не нравится

        No. The fastest way is to precompute all popcounts for 16-bit parts (for int32 case) or 22-bit parts (for int64 case) and calculate the answer in 2 or 3 bit shifts, array element accesses and summations.

        • »
          »
          »
          »
          »
          8 лет назад, # ^ |
            Проголосовать: нравится -15 Проголосовать: не нравится

          Actually __builtin_popcount is faster than so-called array table algorithm (sorry for poor English :), don't know how to express it correctly) is my computer, because the memory reading without cache is slow.

          • »
            »
            »
            »
            »
            »
            8 лет назад, # ^ |
              Проголосовать: нравится +3 Проголосовать: не нравится

            __builtin_popcount should be faster because it compiles into one assembler instruction. But it's not true on codeforces, IIRC MinGW uses bit-shifting algorithm instead.

        • »
          »
          »
          »
          »
          8 лет назад, # ^ |
            Проголосовать: нравится +26 Проголосовать: не нравится
          inline int popcount(int x){
              int count = 0;
              __asm__ volatile("POPCNT %1, %0;"
                  :"=r"(count)
                  :"r"(x)
                  :
              );
              return count;
          }
          
          • »
            »
            »
            »
            »
            »
            4 года назад, # ^ |
              Проголосовать: нравится 0 Проголосовать: не нравится

            How does the above compare to this approach?

            • »
              »
              »
              »
              »
              »
              »
              4 года назад, # ^ |
                Проголосовать: нравится 0 Проголосовать: не нравится

              Well it varies with architecture, compiler flags, SSE enabled/disabled. I don't know of an implementation that dominates the rest all the time. Better to benchmark and see for yourself in the platform of your interest.

  • »
    »
    10 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится

    __builtin_popcount looks to have O (1) complexity. Here is the proposed improvement [1] and the source code [2], look from line number 808.

    [1] https://gcc.gnu.org/bugzilla/show_bug.cgi?id=36041
    [2] https://gcc.gnu.org/viewcvs/gcc/trunk/libgcc/libgcc2.c?view=markup&pathrev=200506

  • »
    »
    4 года назад, # ^ |
      Проголосовать: нравится +34 Проголосовать: не нравится

    It's slow unless you instruct the compiler to use the popcnt instruction.

    #pragma GCC optimize("O3")
    #pragma GCC target("popcnt")
    #include <bits/stdc++.h>
    using namespace std;
    
    typedef long long ll;
    
    int main() {
      ios::sync_with_stdio(!cin.tie(0));
    
      int n;
      ll y = 0;
      cin >> n;
      
      for (int x=0; x<n; x++) {
          y += __builtin_popcountll(x);
      }
      
      cout << y << '\n';
    }
    

    In all tests, $$$n=10^9$$$.

    • Without pragmas, running time is 2245 ms.
    • With just O3, it's 2261 ms.
    • With just popcnt, it's 623 ms.
    • With both, it's 421ms.
»
5 лет назад, # |
Rev. 2   Проголосовать: нравится -25 Проголосовать: не нравится

There is NO __builtin_popcount in c++, it's a built in function of GCC. The function prototype is as follows: int __builtin_popcount(unsigned int) It returns the numbers of set bits in an integer (the number of ones in the binary representation of the integer).

»
4 года назад, # |
  Проголосовать: нравится +8 Проголосовать: не нравится

Lol same thing happened with me in a codechef contest .. and i couldn't spot it during the whole contest

  • »
    »
    4 года назад, # ^ |
    Rev. 2   Проголосовать: нравится 0 Проголосовать: не нравится

    You can use just a bitset<32>(x).count() and bitset<64>(x).count() always. It will be optimized on any online judge, you can check assembly there and you will see only call __popcountdi2 in both cases.

»
2 года назад, # |
  Проголосовать: нравится -13 Проголосовать: не нравится

what is the time complexity of __builtin_popcount() which is used as cpp inbuilt function