http://stxxl.sourceforge.net
<R-Steffen@gmx.de>
<tb@panthema.net>
http://www.boost.org/LICENSE_1_0.txt
#include <stxxl/bits/mng/block_scheduler.h>
#include <stxxl/bits/common/cmdline.h>
#include <iostream>
#include <limits>
using stxxl::int_type;
using stxxl::unsigned_type;
template class stxxl::block_scheduler<stxxl::swappable_block<int_type, 1024> >;
template <class IBT>
void set_pattern_A(IBT& ib)
{
for (int_type i = 0; i < ib.size; ++i)
ib[i] = i;
}
template <class IBT>
int_type test_pattern_A(IBT& ib)
{
int_type num_err = 0;
for (int_type i = 0; i < ib.size; ++i)
num_err += (ib[i] != i);
return num_err;
}
template <class IBT>
void set_pattern_B(IBT& ib)
{
for (int_type i = 0; i < ib.size; ++i)
ib[i] = ib.size - i;
}
template <class IBT>
int_type test_pattern_B(IBT& ib)
{
int_type num_err = 0;
for (int_type i = 0; i < ib.size; ++i)
num_err += (ib[i] != ib.size - i);
return num_err;
}
const int block_size = 1024;
typedef int_type value_type;
unsigned_type internal_memory = 0;
typedef stxxl::block_scheduler<stxxl::swappable_block<value_type, block_size> > block_scheduler_type;
typedef stxxl::swappable_block<value_type, block_size> swappable_block_type;
typedef block_scheduler_type::swappable_block_identifier_type swappable_block_identifier_type;
typedef block_scheduler_type::internal_block_type internal_block_type;
typedef block_scheduler_type::external_block_type external_block_type;
void test1()
{
STXXL_MSG("first test: call all functions");
external_block_type ext_bl;
stxxl::block_manager::get_instance()->new_block(stxxl::striping(), ext_bl);
internal_block_type* int_bl = new internal_block_type;
set_pattern_A(*int_bl);
int_bl->write(ext_bl)->wait();
block_scheduler_type* bs_ptr = new block_scheduler_type(internal_memory);
block_scheduler_type& bs = *bs_ptr;
STXXL_CHECK(! bs.is_simulating());
swappable_block_identifier_type sbi1 = bs.allocate_swappable_block();
STXXL_CHECK2(!bs.is_initialized(sbi1), "new block should not be initialized?");
bs.initialize(sbi1, ext_bl);
{
internal_block_type& ib = bs.acquire(sbi1);
int_type num_err = 0;
for (int_type i = 0; i < block_size; ++i)
num_err += (ib[i] != i);
STXXL_CHECK2(num_err == 0,
"previously initialized block had " << num_err << " errors.");
}
{
internal_block_type& ib = bs.get_internal_block(sbi1);
for (int_type i = 0; i < block_size; ++i)
ib[i] = block_size - i;
bs.release(sbi1, true);
}
swappable_block_identifier_type sbi2 = bs.allocate_swappable_block();
STXXL_CHECK2(!bs.is_initialized(sbi2), "new block should not be initialized?");
{
internal_block_type& ib1 = bs.acquire(sbi1);
internal_block_type& ib2 = bs.acquire(sbi2);
for (int_type i = 0; i < block_size; ++i)
ib2[i] = ib1[i];
bs.release(sbi1, false);
bs.release(sbi2, true);
}
STXXL_CHECK2(bs.is_initialized(sbi1), "block should not be initialized!");
STXXL_CHECK2(bs.is_initialized(sbi2), "block should not be initialized!");
ext_bl = bs.extract_external_block(sbi2);
STXXL_CHECK2(!bs.is_initialized(sbi2), "block should not be initialized after extraction!");
bs.deinitialize(sbi1);
STXXL_CHECK2(!bs.is_initialized(sbi1), "block should not be initialized after deinitialize!");
bs.free_swappable_block(sbi1);
bs.free_swappable_block(sbi2);
bs.explicit_timestep();
stxxl::block_scheduler_algorithm_simulation<swappable_block_type>* asim =
new stxxl::block_scheduler_algorithm_simulation<swappable_block_type>(bs);
delete bs.switch_algorithm_to(asim);
swappable_block_identifier_type sbi = bs.allocate_swappable_block();
bs.acquire(sbi);
bs.acquire(sbi);
bs.release(sbi, true);
bs.explicit_timestep();
bs.release(sbi, false);
bs.deinitialize(sbi);
bs.initialize(sbi, external_block_type());
if (bs.is_simulating())
bs.extract_external_block(sbi);
else
bs.extract_external_block(sbi);
bs.free_swappable_block(sbi);
if (true)
{
block_scheduler_type::prediction_sequence_type ps = bs.get_prediction_sequence();
for (block_scheduler_type::prediction_sequence_type::iterator it = ps.begin(); it != ps.end(); ++it)
STXXL_MSG("id: " << it->id << " op: " << it->op << " t: " << it->time);
}
delete bs.switch_algorithm_to(
new stxxl::block_scheduler_algorithm_offline_lfd<swappable_block_type>(asim));
sbi = bs.allocate_swappable_block();
bs.acquire(sbi);
bs.acquire(sbi);
bs.release(sbi, true);
bs.explicit_timestep();
bs.release(sbi, false);
bs.deinitialize(sbi);
bs.initialize(sbi, external_block_type());
if (bs.is_simulating())
bs.extract_external_block(sbi);
else
bs.extract_external_block(sbi);
bs.free_swappable_block(sbi);
#if 0
delete bs.switch_algorithm_to(
new stxxl::block_scheduler_algorithm_offline_lru_prefetching<swappable_block_type>(asim));
sbi = bs.allocate_swappable_block();
bs.acquire(sbi);
bs.acquire(sbi);
bs.release(sbi, true);
bs.explicit_timestep();
bs.release(sbi, false);
bs.deinitialize(sbi);
bs.initialize(sbi, external_block_type());
if (bs.is_simulating())
bs.extract_external_block(sbi);
else
bs.extract_external_block(sbi);
bs.free_swappable_block(sbi);
#endif
delete bs_ptr;
int_bl->read(ext_bl)->wait();
STXXL_CHECK2(test_pattern_B(*int_bl) == 0,
"after extraction changed block should contain pattern B.");
delete int_bl;
}
void test2()
{
STXXL_MSG("next test: force swapping");
const int_type num_sb = 5;
block_scheduler_type* bs_ptr = new block_scheduler_type(block_size * sizeof(value_type) * 3);
block_scheduler_type& bs = *bs_ptr;
swappable_block_identifier_type sbi[num_sb];
for (int_type i = 0; i < num_sb; ++i)
sbi[i] = bs.allocate_swappable_block();
internal_block_type* ib[num_sb];
ib[0] = &bs.acquire(sbi[0]);
ib[1] = &bs.acquire(sbi[1]);
ib[2] = &bs.acquire(sbi[2]);
set_pattern_A(*ib[0]);
set_pattern_A(*ib[1]);
set_pattern_A(*ib[2]);
bs.release(sbi[0], true);
bs.release(sbi[1], true);
bs.release(sbi[2], true);
ib[3] = &bs.acquire(sbi[3]);
ib[4] = &bs.acquire(sbi[4]);
set_pattern_A(*ib[3]);
set_pattern_A(*ib[4]);
bs.release(sbi[3], true);
bs.release(sbi[4], true);
ib[2] = &bs.acquire(sbi[2]);
ib[3] = &bs.acquire(sbi[3]);
ib[1] = &bs.acquire(sbi[1]);
STXXL_CHECK2(test_pattern_A(*ib[1]) == 0, "Block 1 had errors.");
STXXL_CHECK2(test_pattern_A(*ib[2]) == 0, "Block 2 had errors.");
STXXL_CHECK2(test_pattern_A(*ib[3]) == 0, "Block 3 had errors.");
bs.release(sbi[1], false);
bs.release(sbi[2], false);
bs.release(sbi[3], false);
for (int_type i = 0; i < num_sb; ++i)
bs.free_swappable_block(sbi[i]);
delete bs_ptr;
}
void test3()
{
{
STXXL_MSG("next test: do not free uninitialized block");
block_scheduler_type bs(block_size * sizeof(value_type));
swappable_block_identifier_type sbi;
sbi = bs.allocate_swappable_block();
bs.acquire(sbi);
bs.release(sbi, false);
}
{
STXXL_MSG("next test: do not free initialized block");
block_scheduler_type bs(block_size * sizeof(value_type));
swappable_block_identifier_type sbi;
sbi = bs.allocate_swappable_block();
bs.acquire(sbi);
bs.release(sbi, true);
}
if (0)
{
STXXL_MSG("next test: do not release but free block");
block_scheduler_type bs(block_size * sizeof(value_type));
swappable_block_identifier_type sbi;
sbi = bs.allocate_swappable_block();
bs.acquire(sbi);
bs.free_swappable_block(sbi);
}
{
STXXL_MSG("next test: do neither release nor free block");
block_scheduler_type bs(block_size * sizeof(value_type));
swappable_block_identifier_type sbi;
sbi = bs.allocate_swappable_block();
bs.acquire(sbi);
}
if (0)
{
STXXL_MSG("next test: release block to often");
block_scheduler_type bs(block_size * sizeof(value_type));
swappable_block_identifier_type sbi;
sbi = bs.allocate_swappable_block();
bs.acquire(sbi);
bs.release(sbi, false);
bs.release(sbi, false);
}
}
int main(int argc, char** argv)
{
int test_case = -1;
int internal_memory_megabytes = 256;
stxxl::cmdline_parser cp;
cp.add_int('t', "test-case", "I", "number of the test case to run", test_case);
cp.add_int('m', "memory", "N", "internal memory to use (in megabytes)", internal_memory_megabytes);
cp.set_description("stxxl block_scheduler test");
cp.set_author("Raoul Steffen, R-Steffen@gmx.de");
if (!cp.process(argc, argv))
return -1;
internal_memory = unsigned_type(internal_memory_megabytes) * 1048576;
test1();
test2();
test3();
STXXL_MSG("end of test");
return 0;
}