Search code examples
c++algorithmcudathrust

Why thrust::count and thrust::count_if give diffenrent results for counting how many elements are zero in device vector?


I have a thrust device vector with 16.679.056 float elements in it.

The result of int result_count_0 = thrust::count(d_result.begin(),d_result.end(), 0); is 14.786.283 But at the same time the following approach with thrust::count_if gives a different result (15.733.822)

struct is_zero
{
  __host__ __device__
  bool operator()(int x)
  {
    return x == 0;
  }
};

...
    is_zero iszero;
    int result_count_isZero = thrust::count_if(d_result.begin(),d_result.end(),iszero);

Why is this so? The result of count_if makes more sense, because the number of non zero elements is 945.234 (945234 + 15733822 is 16679056, the exakt size of my device vector).


Solution

  • It seems the difference exists due to tuancations of float numbers to numbers of the type int in the function object

    bool operator()(int x)
    {
      return x == 0;
    }
    

    Change the type of the parameter in the operator function to the type of stored objects.

    Here is a demonstration program that uses standard algorithms std::count and std::count_if that demonstrates the reason of the difference.

    #include <iostream>
    #include <vector>
    #include <algorithm>
    
    int main()
    {
        struct is_zero
        {
            bool operator()( int x ) const
            {
                return x == 0;
            }
        };
    
        std::vector<float> v = { 1.0f, 0.0f, 0.5f, -0.9f };
    
        std::cout << std::count( v.begin(), v.end(), 0.0f ) << '\n';
        std::cout << std::count_if( v.begin(), v.end(), is_zero() ) << '\n';
    }
    

    The program output is

    1
    3