Another not successful try to messure memory bandwith.

This commit is contained in:
2013-07-08 18:02:34 +04:00
parent f483c1725d
commit 395c6f49db

View File

@@ -2,17 +2,23 @@
VIM: let g:lcppflags="-std=c++11 -O2 -pthread" VIM: let g:lcppflags="-std=c++11 -O2 -pthread"
VIM: let g:wcppflags="/O2 /EHsc /DWIN32" VIM: let g:wcppflags="/O2 /EHsc /DWIN32"
VIM: let g:cppflags=g:Iboost VIM: let g:cppflags=g:Iboost
VIM-: let g:wldflags=/DEBUG
VIM: let g:ldflags=g:Lboost VIM: let g:ldflags=g:Lboost
VIM: let g:ldlibpath=g:Bboost VIM: let g:ldlibpath=g:Bboost
VIM: let g:argv="" VIM: let g:argv=""
VIM-: let g:cf5output=0 VIM-: let g:cf5output=0
*/ */
#include <sstream>
#include <iostream> #include <iostream>
#include <iomanip> #include <iomanip>
#include <exception> #include <exception>
#include <chrono> #include <chrono>
#include <algorithm> #include <algorithm>
#include <vector>
#include <utility>
#include <cmath>
#if 0
typedef long long duration_type; typedef long long duration_type;
static const size_t ce = 1024L*1024L*1024L; static const size_t ce = 1024L*1024L*1024L;
@@ -74,22 +80,188 @@ void test_steps( F f , char * p, const size_t c, char * nm )
std::cout << std::setw(16) << dev << std::endl; std::cout << std::setw(16) << dev << std::endl;
} }
} }
#endif
void test_workingset( const size_t c ) static const size_t GB = 1024L*1024L*1024L;
class tests
{ {
char * p = (char*)malloc( c ); public:
typedef long long duration_type;
typedef void * elem_type;
public:
size_t const workset;
size_t const cnt;
elem_type * const mem;
std::vector<duration_type> res;
public:
tests( size_t _ws = GB )
: workset(_ws)
, cnt(workset/sizeof(elem_type))
, mem((elem_type*)malloc( workset ))
{
}
~tests()
{
free(mem);
}
public:
void print_hdr( const char * title,
const char * param,
const char * action )
{
std::cout << std::endl << title << std::endl
<< std::setfill('-') << std::setw(90) << "" << std::endl
<< std::setfill(' ')
<< std::setw(10) << param
<< std::setw(14) << action << "#1"
<< std::setw(14) << action << "#2"
<< std::setw(14) << action << "#3"
<< std::setw(16) << "average"
<< std::setw(16) << "deviation" << std::endl;
}
std::cout << "Working set " << c << std::endl ; void print_param( size_t param )
test_steps( scan_read, p, c, "read" ); {
test_steps( scan_write, p, c, "write" ); std::cout << std::setw(10) << param << std::flush;
} }
void print_time( duration_type d )
{
std::cout << std::setw(16) << d << std::flush;
}
void print_avrg( duration_type avrg, duration_type dev )
{
std::cout << std::setw(16) << avrg;
std::cout << std::setw(16) << dev << std::endl;
}
void evict()
{
for ( elem_type * p = mem, * const pe = mem+cnt; p < pe; ++p )
*p = 0;
}
//
// Calculate average of tests duration and the deviation.
//
std::pair<duration_type,duration_type>
average( const duration_type * test, const size_t count )
{
//
// Calc average duration.
//
duration_type avrg = 0;
for ( int i = 0; i < count; ++i )
avrg += test[i];
avrg /= count;
//
// Calc deviation from average duration.
//
duration_type dev = 0;
for ( int i = 0; i < count; ++i )
dev += std::abs( avrg - test[i] );
dev /= count;
//
return std::make_pair(avrg,dev);
}
__declspec(noinline)
duration_type scan_read( elem_type const * const p, const size_t c, const size_t s )
{
auto b = std::chrono::high_resolution_clock::now();
//
register elem_type sum = 0;
elem_type const * const qe = p+c;
for ( int r =0, re=cnt/c; r < re; ++r )
for ( size_t i = 0; i < s; ++i )
for ( elem_type const * q = p+i; q < qe; q+=s )
sum = *q;
//
// Prevents optimisation of the loop.
//
volatile elem_type no_optimization = sum;
//
auto e = std::chrono::high_resolution_clock::now();
return std::chrono::nanoseconds(e-b).count();
}
void benchmark_read_time(int s)
{
std::stringstream ss;
ss << "Memory continuous read. Step=" << s*sizeof(elem_type);
print_hdr( ss.str().c_str(), "wset", "read" );
const int trys = 3;
duration_type test[trys];
size_t c = 8;
for ( ; c < s; c <<=1 )
res.push_back( -1 );
for ( ; c <= cnt; c <<=1 )
{
print_param( c*sizeof(elem_type) );
for ( int t = 0; t < trys; ++t )
{
evict();
test[t] = scan_read( mem, c, s );
print_time( test[t] );
}
auto a = average( test, trys );
res.push_back( a.first );
print_avrg( a.first, a.second );
}
}
void benchmark_read_time()
{
size_t const se = cnt;
for ( size_t s = 1; s <= se; s <<=1 )
benchmark_read_time(s);
//
// Print header.
//
std::cout << std::endl << "Read time test." << std::endl
<< std::setfill('-') << std::setw(90) << "" << std::endl
<< std::setfill(' ')
<< std::setw(10) << "wset";
for ( size_t s = 1; s <= se; s <<=1 )
{
std::stringstream ss;
ss << "s" << s*sizeof(elem_type);
std::cout << std::setw(16) << ss.str();
}
std::cout << std::endl;
//
// Print results.
//
std::cout << std::log(double(se))/std::log(2.) << " ";
size_t const je = std::log(double(se))/std::log(2.)+1;
size_t const ie = res.size()/je;
std::cout << res.size() << " " << je << " " << ie << std::endl;
for ( size_t i = 0, c = 8; i < ie; ++i, c <<=1 )
{
std::cout << std::setw(10) << c*sizeof(elem_type);
for ( size_t j = i; j < res.size(); j+=ie )
std::cout << std::setw(16) << res[j];
std::cout << std::endl;
}
}
};
int main ( void ) int main ( void )
{try{ {try{
tests t;
for ( size_t c = 4096; c <= ce; c <<=1 ) t.benchmark_read_time();
test_workingset( c );
return 0; return 0;
} }