Liste des Groupes | Revenir à cl c++ |
Now I wrote a little program to test if there's thundering herd problemSigh... Here is a challenge for you. Get it working in a race detector, say, Relacy?
with glibc's mutex / condvar. This it is:
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <atomic>
#include <semaphore>
#include <vector>
#include <sys/resource.h>
using namespace std;
int main()
{
constexpr size_t N = 10'000;
int nClients = thread::hardware_concurrency() - 1;
mutex mtx;
int signalled = 0;
condition_variable cv;
atomic_int ai( 0 );
binary_semaphore bs( false );
vector<jthread> clients;
atomic_int64_t nVoluntary( 0 );
for( int c = nClients; c; --c )
clients.emplace_back( [&]
{
for( size_t r = N; r; --r )
{
unique_lock lock( mtx );
cv.wait( lock, [&] { return (bool)signalled; } );
--signalled;
lock.unlock();
if( ai.fetch_sub( 1, memory_order_relaxed ) == 1 )
bs.release( 1 );
}
rusage ru;
getrusage( RUSAGE_THREAD, &ru );
nVoluntary.fetch_add( ru.ru_nvcsw, memory_order_relaxed );
} );
for( size_t r = N; r; --r )
{
unique_lock lock( mtx );
signalled = nClients;
cv.notify_all();
ai.store( nClients, memory_order_relaxed );
lock.unlock();
bs.acquire();
}
clients.resize( 0 );
cout << N << " rounds," << endl;
cout << (double)nVoluntary.load( memory_order_relaxed ) / nClients << " context switches pe thread" << endl;
}
It spawns one less threads than ther are hardware threads. These
all wait for a condvar and a counter which is initially the number
of threads and that must be > 0 for the wait to succeed. This counter
is decremented by each thread. Then the threads decrement an atomic
and if it becomes zero the last thread raises a semaphore, thereby
waking up the main thread.
This are the results for 10'000 rounds on a 32-thread machine:
10000 rounds,
2777.29 context switches pe thread
So there are less context-switches than rounds and there's no
thundering herd with glibc.
Les messages affichés proviennent d'usenet.