Skip to content

Instantly share code, notes, and snippets.

@ACUVE

ACUVE/main.cpp Secret

Created December 16, 2015 08:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ACUVE/b21fc57cfe5e315b949e to your computer and use it in GitHub Desktop.
Save ACUVE/b21fc57cfe5e315b949e to your computer and use it in GitHub Desktop.
#include <atomic>
#include <chrono>
#include <iostream>
#include <limits>
#include <condition_variable>
#include <thread>
#include <vector>
#include <omp.h>
template< typename FUNC, typename... Args >
inline std::chrono::nanoseconds time( FUNC &&func, Args &&... args )
{
auto const start = std::chrono::high_resolution_clock::now();
func( std::forward< Args >( args )... );
auto const end = std::chrono::high_resolution_clock::now();
auto const duration = end - start;
return std::chrono::duration_cast< std::chrono::nanoseconds >( duration );
}
class ThreadPool
{
public:
using func_type = void (*)( void *data, unsigned int num, unsigned int thread_num );
private:
std::atomic< func_type > func;
std::atomic< void * > func_data;
std::atomic< unsigned int > waiting_counter;
std::atomic< unsigned int > counter;
unsigned int const num_thread;
std::vector< std::thread > thread;
private:
void WaitAllWaiting()
{
unsigned int const len = num_thread - 1;
while( waiting_counter.load() != len )
std::this_thread::yield();
}
public:
ThreadPool( unsigned int const hc = std::thread::hardware_concurrency() )
: func( nullptr )
, func_data( nullptr )
, waiting_counter( 0 )
, counter( 0 )
, num_thread( [ & ]{ if( hc ) return hc; return 1u; }() )
{
unsigned int const len = num_thread - 1;
for( unsigned int i = 0; i < len; ++i )
thread.emplace_back( &ThreadPool::Thread, this, i );
WaitAllWaiting();
}
~ThreadPool()
{
func.store( nullptr );
counter.fetch_add( 1 );
for( auto &&th : thread )
th.join();
}
void Thread( unsigned int const num )
{
unsigned int c = counter.load();
unsigned int const num_t = num_thread;
while( true )
{
waiting_counter.fetch_add( 1 );
while( counter.load() == c )
std::this_thread::yield();
c = counter.load();
auto f = func.load();
if( !f )
break;
f( func_data.load(), num, num_t );
}
}
void Do( func_type f, void *data )
{
if( f == nullptr )
return;
func.store( f );
func_data.store( data );
waiting_counter.store( 0 );
counter.fetch_add( 1 );
f( data, num_thread - 1, num_thread );
WaitAllWaiting();
}
};
struct ThreadData
{
unsigned int c;
std::atomic< double > *s;
};
void aaa( void *data, unsigned int const num, unsigned int const thread_num )
{
auto const td = reinterpret_cast< ThreadData * >( data );
auto const c = td->c;
std::atomic< double > *const ret = td->s;
decltype( c ) const
part = c / thread_num,
rest = c % thread_num,
s = part * num + (num < rest ? num : rest),
e = s + part + (num + 1 < rest);
double sum = 0;
double const delta = 1.0 / c;
for( auto i = s; i < e; ++i )
{
double const x = (delta * i);
double const area = delta * 1.0 / (x * x + 1.0);
sum += area;
}
double expected = ret->load();
while( !std::atomic_compare_exchange_weak( ret, &expected, expected + sum ) );
}
void openmp( std::atomic< double > *const v, unsigned int const c )
{
double sum = 0;
double const delta = 1.0 / c;
#pragma omp parallel for reduction ( + : sum )
for( unsigned int i = 0; i < c; ++i )
{
double const x = (delta * i);
double const area = delta * 1.0 / (x * x + 1.0);
sum += area;
}
v->store( sum );
}
int main( int argc, char **argv )
{
std::atomic< double > v;
unsigned int const count = 1000 * 1000 * argc;
{
ThreadPool pool;
ThreadData td;
td.c = count;
td.s = &v;
for( unsigned int i = 0; i < 10; ++i )
{
v = 0;
std::cout << "time = " << time( std::bind( &ThreadPool::Do, &pool, aaa, &td ) ).count() << std::endl;
std::cout << v << std::endl;
}
std::this_thread::sleep_for( std::chrono::seconds( 5 ) );
}
std::cout << "-------------------------------------" << std::endl;
{
for( unsigned int i = 0; i < 10; ++i )
{
v = 0;
std::cout << "time = " << time( openmp, &v, count ).count() << std::endl;
std::cout << v << std::endl;
}
std::this_thread::sleep_for( std::chrono::seconds( 5 ) );
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment