G
hustbaer schrieb:
@GorbGorb:
Ich würde 1) nicht machen, weil ... weiss nicht. Stört mich einfach nicht dass ich .reset() schreiben muss.
Zu 2x vs. 100x: mit was für einer CPU testest du das? P4 und Core2 brauchen
, wenn mich meine Erinnerung jetzt nicht trügt, so ca. 400 Cycles für ein InterlockedIncrement (wohingegen ein normales so bei 0,3-1 Cycles liegt).
Ich benutze einen Core i5. Das ist der code, mit dem ich es getestet habe:
#include <iostream>
#include <ctime>
#include <atomic>
#include <boost/thread.hpp>
template< class A >
void measure( const char *name , A &&functor_a )
{
unsigned int t = std::clock();
boost::thread thread_a( functor_a );
thread_a.join();
std::cout << name << std::clock() - t << std::endl;
}
template< class A , class B >
void measure( const char *name , A &&functor_a , B &&functor_b )
{
unsigned int t = std::clock();
boost::thread thread_a( functor_a );
boost::thread thread_b( functor_b );
thread_a.join();
thread_b.join();
std::cout << name << std::clock() - t << std::endl;
}
std::atomic< int > a( 0 );
volatile unsigned int n1 = 0;
volatile unsigned int n2 = 0;
volatile unsigned int volatile_test = 0;
const unsigned int loop_number = 20000;
int main()
{
auto threadfunc_a = []()
{
for( unsigned int i = 0 ; i < loop_number ; ++i )
{
a.fetch_sub(1, std::memory_order_release);
a.fetch_sub(1, std::memory_order_release);
a.fetch_sub(1, std::memory_order_release);
a.fetch_sub(1, std::memory_order_release);
a.fetch_sub(1, std::memory_order_release);
a.fetch_sub(1, std::memory_order_release);
a.fetch_sub(1, std::memory_order_release);
a.fetch_sub(1, std::memory_order_release);
}
};
auto threadfunc_n1 = []()
{
for( unsigned int i = 0 ; i < loop_number ; ++i )
{
--n1;
--n1;
--n1;
--n1;
--n1;
--n1;
--n1;
--n1;
}
};
auto threadfunc_n2 = []()
{
for( unsigned int i = 0 ; i < loop_number ; ++i )
{
--n2;
--n2;
--n2;
--n2;
--n2;
--n2;
--n2;
--n2;
}
};
auto threadfunc_volatile_test = []()
{
for( unsigned int i = 0 ; i < loop_number ; ++i )
--volatile_test;
};
measure( "atomic 1 thread: " , threadfunc_a );
measure( "volatile 1 thread: " , threadfunc_n1 );
measure( "volatile test 1 thread: " , threadfunc_volatile_test );
measure( "atomic 2 threads: " , threadfunc_a , threadfunc_a );
measure( "volatile 2 threads: " , threadfunc_n1 , threadfunc_n2 );
std::cin.get();
return 0;
}
Was mich daran ernsthaft beunruhigt, ist, dass sich das Programm ab loopnumber ~ 10000 regelmäßig aufhängt... Woran könnte das liegen?
Ausgabe mit loopnumber = 20000:
atomic 1 thread: 4
volatile 1 thread: 1
single volatile 1 thread: 1
atomic 2 threads: 7
volatile 2 threads: 4
Damit kann man leider nicht allzu viel anfangen, std::clock() ist ja nicht besonders genau...
Die Ausgabe bei loopnumber = 10000000, soweit es eben gekommen ist:
atomic 1 thread: 1018
volatile 1 thread: 425
volatile test 1 thread: 52