Boost logo

Boost Users :

Subject: Re: [Boost-users] [boost.numeric] Poor Performance of numeric_cast
From: Oswin Krause (Oswin.Krause_at_[hidden])
Date: 2012-10-16 01:24:55


Hi,

the results turnd out to have a high variance due to the low time
usage. SInce just choosing higher count numbers already lead to an
overflow, i hacked in the following loop:

nanoseconds profile( PROFILE_FUNC _profileFunc, uint32_t _count )
{
high_resolution_clock::time_point start = high_resolution_clock::now();
double summ = 0;
for(std::size_t i = 0; i != 100000; ++i){
        uint32_t sum = i;
        _profileFunc( _count, sum );
        summ +=sum;
}

nanoseconds ns = ( high_resolution_clock::now() - start ) / _count;

cout << summ << endl;

return ns;
}

results:

Native Integer Cast: 26729 nanoseconds
Boost Integer Cast: 26449 nanoseconds
Native Integer-Floating Cast: 105479 nanoseconds
Boost Integer-Floating Cast: 105455 nanoseconds
Native Floating-Integer Cast: 168933 nanoseconds
Boost Floating-Integer Cast: 453505 nanoseconds

so no overhead in Integer-Integer or Integer-Floating. But
Floating-Integer has bad performance.

On 2012-10-16 06:45, Tang Jiang Jun wrote:
> I've already tried to remove all the try-catch blocks, but the
> overhead is still there.
> On the other side, when casting a number, it is general to use a
> dedicated try-catch block to protect it.
>
> On Tue, Oct 16, 2012 at 12:08 PM, Brian Budge <brian.budge_at_[hidden]
> [15]> wrote:
>
>> Unsure, but maybe you should put the try/catch outside of the inner
>> loop?
>>
>> On Mon, Oct 15, 2012 at 8:50 PM, Tang Jiang Jun
>> <tangjiangjun_at_[hidden] [1]> wrote:
>> > Hi,
>> >
>> > I modify my code to make it can run in release mode without
>> unintended
>> > optimization, and now the performance is acceptable. However
>> there
>> > definitely has some runtime overhead even no overflow happens,
>> and the
>> > overhead takes extra time as much as the plain cast itself takes.
>> I think
>> > this maybe should be mentioned in the numeric_cast document,
>> because if the
>> > cast is the core step in an algorithms and is executed heavily,
>> this
>> > overhead will impact the performance significantly .
>> >
>> > The following is the benchmark code after modification and the
>> result run in
>> > my computer.
>> >
>> > CODE
>> > #include <boost/numeric/conversion/cast.hpp>
>> >
>> > #include <boost/format.hpp>
>> > #include <boost/cstdint.hpp>
>> > #include <boost/chrono.hpp>
>> > #include <iostream>
>> >
>> > using namespace std;
>> > using namespace boost;
>> > using namespace boost::numeric;
>> > using namespace boost::chrono;
>> >
>> >
>> > typedef void (*PROFILE_FUNC)( uint32_t, uint32_t& );
>> >
>> > nanoseconds profile( PROFILE_FUNC _profileFunc, uint32_t _count )
>> > {
>> >     high_resolution_clock::time_point start =
>> high_resolution_clock::now();
>> >
>> >     uint32_t sum = 0;
>> >     _profileFunc( _count, sum );
>> >
>> >     nanoseconds ns = ( high_resolution_clock::now() - start ) /
>> _count;
>> >
>> >     cout << sum << endl;
>> >
>> >     return ns;
>> > }
>> >
>> >
>> > void native_integer_cast( uint32_t _count, uint32_t& _sum )
>> > {
>> >     for( uint64_t n = 0; n < _count; ++n )
>> >     {
>> >         _sum += static_cast< uint32_t >( n );
>> >     }
>> > }
>> >
>> >
>> > void boost_integer_cast( uint32_t _count, uint32_t& _sum )
>> > {
>> >     for( uint64_t n = 0; n < _count; ++n )
>> >     {
>> >         try
>> >         {
>> >             _sum += numeric_cast< uint32_t >( n );
>> >
>> >         }
>> >         catch( const bad_numeric_cast& e )
>> >         {
>> >             cout << e.what() << endl;
>> >         }
>> >     }
>> > }
>> >
>> >
>> > void native_itof_cast( uint32_t _count, uint32_t& _sum )
>> > {
>> >     float fsum = 0.0f;
>> >
>> >     for( uint32_t n = 0; n < _count; ++n )
>> >     {
>> >         fsum += static_cast< float >( n );
>> >     }
>> >
>> >     _sum = static_cast< uint32_t >( fsum );
>> > }
>> >
>> >
>> > void boost_itof_cast( uint32_t _count, uint32_t& _sum )
>> > {
>> >     float fsum = 0.0f;
>> >
>> >     for( uint32_t n = 0; n < _count; ++n )
>> >     {
>> >         try
>> >         {
>> >             fsum += numeric_cast< float >( n );
>> >
>> >         }
>> >         catch( const bad_numeric_cast& e )
>> >         {
>> >             cout << e.what() << endl;
>> >         }
>> >     }
>> >
>> >     _sum = numeric_cast< uint32_t >( fsum );
>> > }
>> >
>> >
>> > void native_ftoi_cast( uint32_t _count, uint32_t& _sum )
>> > {
>> >     for( float f = 0.0f; f < _count; f += 1.0f )
>> >     {
>> >         _sum += static_cast< uint32_t >( f );
>> >     }
>> > }
>> >
>> >
>> > void boost_ftoi_cast( uint32_t _count, uint32_t& _sum )
>> > {
>> >     for( float f = 0.0f; f < _count; f += 1.0f )
>> >     {
>> >         try
>> >         {
>> >             _sum += numeric_cast< uint32_t >( f );
>> >
>> >         }
>> >         catch( const bad_numeric_cast& e )
>> >         {
>> >             cout << e.what() << endl;
>> >         }
>> >     }
>> > }
>> >
>> >
>> >
>> > int main()
>> > {
>> >     const static int32_t COUNT = 10000;
>> >
>> >     nanoseconds nsNativeIntegerCast = profile(
>> native_integer_cast, COUNT );
>> >     nanoseconds nsBoostIntegerCast = profile(
>> boost_integer_cast, COUNT );
>> >     nanoseconds nsNativeItofCast = profile( native_itof_cast,
>> COUNT );
>> >     nanoseconds nsBoostItofCast = profile( boost_itof_cast,
>> COUNT );
>> >     nanoseconds nsNativeFtoiCast = profile( native_ftoi_cast,
>> COUNT );
>> >     nanoseconds nsBoostFtoiCast = profile( boost_ftoi_cast,
>> COUNT );
>> >
>> >     cout << "Native Integer Cast: " << nsNativeIntegerCast <<
>> endl;
>> >     cout << "Boost Integer Cast: " << nsBoostIntegerCast <<
>> endl;
>> >     cout << "Native Integer-Floating Cast: " <<
>> nsNativeItofCast << endl;
>> >     cout << "Boost Integer-Floating Cast: " << nsBoostItofCast
>> << endl;
>> >     cout << "Native Floating-Integer Cast: " <<
>> nsNativeFtoiCast << endl;
>> >     cout << "Boost Floating-Integer Cast: " << nsBoostFtoiCast
>> << endl;
>> >
>> >     return 0;
>> > };
>> >
>> >
>> > RESULT:
>> > Native Integer Cast: 1 nanosecond
>> > Boost Integer Cast: 4 nanoseconds
>> > Native Integer-Floating Cast: 3 nanoseconds
>> > Boost Integer-Floating Cast: 3 nanoseconds
>> > Native Floating-Integer Cast: 5 nanoseconds
>> > Boost Floating-Integer Cast: 14 nanoseconds
>> >
>> > Regards,
>> > Tang
>> >
>> >
>> > On Mon, Oct 15, 2012 at 6:43 PM, Oswin Krause
>> > <Oswin.Krause_at_[hidden] [2]> wrote:
>> >>
>> >> Hi,
>> >>
>> >> Never benchmark in debug mode. Moreover, never ever benchmark
>> boost code
>> >> in debug mode.
>> >>
>> >>
>> >> On 2012-10-15 11:29, Tang Jiang Jun wrote:
>> >>>
>> >>> Hi Oswin,
>> >>>
>> >>> Sorry, I forgot to mention that I compiled it as debug
>> configuration
>> >>> in order to prevent unintended optimization.
>> >>> Anyway, many thanks for reminding!
>> >>>
>> >>> Tang
>> >>>
>> >>>
>> >>> On Mon, Oct 15, 2012 at 4:30 PM, Oswin Krause
>> >>> <Oswin.Krause_at_[hidden] [3] [3]> wrote:
>> >>>
>> >>>> Hi,
>> >>>>
>> >>>> Your complete loop got optimized away in the native test
>> cases.
>> >>>> Because of the try/catch block the compiler couldn't do this
>> in the
>> >>>> other cases. So you are benchmarking nothing vs somthing.
>> >>>>
>> >>>> Greetings,
>> >>>> Oswin
>> >>>>
>> >>>> On 2012-10-15 10:16, Tang Jiang Jun wrote:
>> >>>>
>> >>>>> Hi,
>> >>>>>
>> >>>>> I have run a performance testing for numeric_cast recently,
>> and
>> >>>>> found
>> >>>>> that the result was really unexpected bad, although the
>> document
>> >>>>> mentioned that it will be no overhead if overflows don't
>> happen.
>> >>>>> Could somebody please help me to verify this testing? If this
>> is
>> >>>>> true,
>> >>>>> I doubt whether I should use numeric_cast in the production
>> code.
>> >>>>>
>> >>>>> Here is my testing code and result.
>> >>>>>
>> >>>>> #include <boost/numeric/conversion/cast.hpp>
>> >>>>> #include <boost/format.hpp>
>> >>>>> #include <boost/cstdint.hpp>
>> >>>>>  #include <boost/chrono.hpp>
>> >>>>> #include <iostream>
>> >>>>>
>> >>>>> using namespace std;
>> >>>>> using namespace boost;
>> >>>>> using namespace boost::numeric;
>> >>>>> using namespace boost::chrono;
>> >>>>>
>> >>>>> int main()
>> >>>>> {
>> >>>>>     const static int32_t COUNT = 1000000;
>> >>>>>     high_resolution_clock::time_point start;
>> >>>>>
>> >>>>>      start = high_resolution_clock::now();
>> >>>>>     for( int32_t n = 0; n < COUNT; ++n )
>> >>>>>     {
>> >>>>>         int32_t i32 = 123;
>> >>>>>         int16_t i16 = i32;
>> >>>>>     }
>> >>>>>     cout << format("Native Integer Cast: %1%n") % ( (
>> >>>>>
>> >>>>> high_resolution_clock::now() - start ) / COUNT );
>> >>>>>
>> >>>>>     start = high_resolution_clock::now();
>> >>>>>     for( int32_t n = 0; n < COUNT; ++n )
>> >>>>>     {
>> >>>>>         try
>> >>>>>         {
>> >>>>>             int32_t i32 = 100;
>> >>>>>             int16_t i16 = numeric_cast< int16_t >( i32
>> >>>>> );
>> >>>>>          }
>> >>>>>         catch( const bad_numeric_cast& e )
>> >>>>>         {
>> >>>>>             cout << e.what() << endl;
>> >>>>>         }
>> >>>>>     }
>> >>>>>     cout << format("Boost Integer Cast: %1%n") % ( (
>> >>>>>
>> >>>>> high_resolution_clock::now() - start ) / COUNT );
>> >>>>>
>> >>>>>     start = high_resolution_clock::now();
>> >>>>>     for( int32_t n = 0; n < COUNT; ++n )
>> >>>>>     {
>> >>>>>         float f = 100.0f;
>> >>>>>         int32_t i = static_cast< int32_t >( f );
>> >>>>>     }
>> >>>>>     cout << format("Native Floating-Integer Cast: %1%n") %
>> ( (
>> >>>>>
>> >>>>> high_resolution_clock::now() - start ) / COUNT );
>> >>>>>
>> >>>>>     start = high_resolution_clock::now();
>> >>>>>     for( int32_t n = 0; n < COUNT; ++n )
>> >>>>>     {
>> >>>>>         try
>> >>>>>         {
>> >>>>>             float f = 123.0f;
>> >>>>>             int32_t i = numeric_cast< int32_t >( f );
>> >>>>>          }
>> >>>>>         catch( const bad_numeric_cast& e )
>> >>>>>         {
>> >>>>>             cout << e.what() << endl;
>> >>>>>         }
>> >>>>>     }
>> >>>>>     cout << format("Boost Floating-Integer Cast: %1%n") % (
>> (
>> >>>>>
>> >>>>> high_resolution_clock::now() - start ) / COUNT );
>> >>>>>
>> >>>>>     start = high_resolution_clock::now();
>> >>>>>     for( int32_t n = 0; n < COUNT; ++n )
>> >>>>>     {
>> >>>>>         int32_t i = 132;
>> >>>>>         float f = static_cast< float >( i );
>> >>>>>     }
>> >>>>>     cout << format("Native Integer-Floating Cast: %1%n") %
>> ( (
>> >>>>>
>> >>>>> high_resolution_clock::now() - start ) / COUNT );
>> >>>>>
>> >>>>>     start = high_resolution_clock::now();
>> >>>>>     for( int32_t n = 0; n < COUNT; ++n )
>> >>>>>     {
>> >>>>>         try
>> >>>>>         {
>> >>>>>             int32_t i = 128;
>> >>>>>             float f = numeric_cast< float >( i );
>> >>>>>          }
>> >>>>>         catch( const bad_numeric_cast& e )
>> >>>>>         {
>> >>>>>             cout << e.what() << endl;
>> >>>>>         }
>> >>>>>     }
>> >>>>>     cout << format("Boost Integer-Floating Cast: %1%n") % (
>> (
>> >>>>>
>> >>>>> high_resolution_clock::now() - start ) / COUNT );
>> >>>>>
>> >>>>>     return 0;
>> >>>>> };
>> >>>>>
>> >>>>> Result:
>> >>>>> Native Integer Cast: 3 nanoseconds
>> >>>>> Boost Integer Cast: 311 nanoseconds
>> >>>>> Native Floating-Integer Cast: 4 nanoseconds
>> >>>>>  Boost Floating-Integer Cast: 430 nanoseconds
>> >>>>> Native Integer-Floating Cast: 2 nanoseconds
>> >>>>> Boost Integer-Floating Cast: 106 nanoseconds
>> >>>>
>> >>>>
>> >>>> _______________________________________________
>> >>>> Boost-users mailing list
>> >>>> Boost-users_at_[hidden] [4] [1]
>> >>>> http://lists.boost.org/mailman/listinfo.cgi/boost-users [5]
>> [2]
>> >>>
>> >>>
>> >>>
>> >>>
>> >>> Links:
>> >>> ------
>> >>> [1] mailto:Boost-users_at_[hidden] [6]
>> >>> [2] http://lists.boost.org/mailman/listinfo.cgi/boost-users [7]
>> >>> [3] mailto:Oswin.Krause_at_[hidden] [8]
>> >>
>> >>
>> >> _______________________________________________
>> >> Boost-users mailing list
>> >> Boost-users_at_[hidden] [9]
>> >> http://lists.boost.org/mailman/listinfo.cgi/boost-users [10]
>> >
>> >
>> >
>> > _______________________________________________
>> > Boost-users mailing list
>> > Boost-users_at_[hidden] [11]
>> > http://lists.boost.org/mailman/listinfo.cgi/boost-users [12]
>> _______________________________________________
>> Boost-users mailing list
>> Boost-users_at_[hidden] [13]
>> http://lists.boost.org/mailman/listinfo.cgi/boost-users [14]
>
>
>
> Links:
> ------
> [1] mailto:tangjiangjun_at_[hidden]
> [2] mailto:Oswin.Krause_at_[hidden]
> [3] mailto:Oswin.Krause_at_[hidden]
> [4] mailto:Boost-users_at_[hidden]
> [5] http://lists.boost.org/mailman/listinfo.cgi/boost-users
> [6] mailto:Boost-users_at_[hidden]
> [7] http://lists.boost.org/mailman/listinfo.cgi/boost-users
> [8] mailto:Oswin.Krause_at_[hidden]
> [9] mailto:Boost-users_at_[hidden]
> [10] http://lists.boost.org/mailman/listinfo.cgi/boost-users
> [11] mailto:Boost-users_at_[hidden]
> [12] http://lists.boost.org/mailman/listinfo.cgi/boost-users
> [13] mailto:Boost-users_at_[hidden]
> [14] http://lists.boost.org/mailman/listinfo.cgi/boost-users
> [15] mailto:brian.budge_at_[hidden]


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net