Stxxl  1.4.0
io/iobench_scatter_in_place.cpp
Go to the documentation of this file.
00001 /***************************************************************************
00002  *  io/iobench_scatter_in_place.cpp
00003  *
00004  *  Part of the STXXL. See http://stxxl.sourceforge.net
00005  *
00006  *  Copyright (C) 2009 Andreas Beckmann <beckmann@cs.uni-frankfurt.de>
00007  *
00008  *  Distributed under the Boost Software License, Version 1.0.
00009  *  (See accompanying file LICENSE_1_0.txt or copy at
00010  *  http://www.boost.org/LICENSE_1_0.txt)
00011  **************************************************************************/
00012 
00013 #include <iomanip>
00014 #include <vector>
00015 #include <cstdio>
00016 
00017 #include <stxxl/io>
00018 #include <stxxl/aligned_alloc>
00019 #include <stxxl/timer>
00020 
00021 
00022 using stxxl::request_ptr;
00023 using stxxl::file;
00024 using stxxl::timer;
00025 using stxxl::uint64;
00026 
00027 
00028 #ifndef BLOCK_ALIGN
00029  #define BLOCK_ALIGN  4096
00030 #endif
00031 
00032 
00033 #define MB (1024 * 1024)
00034 #define GB (1024 * 1024 * 1024)
00035 
00036 void usage(const char * argv0)
00037 {
00038     std::cout << "Usage: " << argv0 << " num_blocks blocks_per_round block_size file" << std::endl;
00039     std::cout << "    'block_size' in bytes" << std::endl;
00040     std::cout << "    'file' is split into 'num_blocks' files of size 'block_size'," << std::endl;
00041     std::cout << "    reading chunks of 'blocks_per_round' blocks starting from end-of-file" << std::endl;
00042     std::cout << "    and truncating the input file after each chunk was read," << std::endl;
00043     std::cout << "    before writing the chunk to new files" << std::endl;
00044     exit(-1);
00045 }
00046 
00047 // returns throughput in MiB/s
00048 inline double throughput(double bytes, double seconds)
00049 {
00050     if (seconds == 0.0)
00051         return 0.0;
00052     return bytes / (1024 * 1024) / seconds;
00053 }
00054 
00055 int main(int argc, char * argv[])
00056 {
00057     if (argc < 5)
00058         usage(argv[0]);
00059 
00060     uint64 num_blocks = stxxl::atoint64(argv[1]);
00061     uint64 blocks_per_round = stxxl::atoint64(argv[2]);
00062     uint64 block_size = stxxl::atoint64(argv[3]);
00063     const char * filebase = argv[4];
00064 
00065     uint64 num_rounds = stxxl::div_ceil(num_blocks, blocks_per_round);
00066 
00067     std::cout << "# Splitting '" << filebase << "' into "
00068               << num_rounds * blocks_per_round << " blocks of size "
00069               << block_size << ", reading chunks of "
00070               << blocks_per_round << " blocks" << std::endl;
00071 
00072     char * buffer = (char *)stxxl::aligned_alloc<BLOCK_ALIGN>(block_size * blocks_per_round);
00073     double totaltimeread = 0, totaltimewrite = 0;
00074     stxxl::int64 totalsizeread = 0, totalsizewrite = 0;
00075     double totaltimereadchunk = 0.0, totaltimewritechunk = 0.0;
00076     stxxl::int64 totalsizereadchunk = 0, totalsizewritechunk = 0;
00077 
00078     typedef stxxl::syscall_file file_type;
00079 
00080     file_type input_file(filebase, file::RDWR | file::DIRECT, 0);
00081 
00082     timer t_total(true);
00083     try {
00084         for (stxxl::unsigned_type r = num_rounds; r-- > 0; )
00085         {
00086             // read a chunk of blocks_per_round blocks
00087             timer t_read(true);
00088             for (stxxl::unsigned_type i = blocks_per_round; i-- > 0; )
00089             {
00090                 const uint64 offset = (r * blocks_per_round + i) * block_size;
00091                 timer t_op(true);
00092                 // read a block
00093                 {
00094                     input_file.aread(buffer + i * block_size, offset, block_size, stxxl::default_completion_handler())->wait();
00095                 }
00096                 t_op.stop();
00097                 totalsizeread += block_size;
00098                 totaltimeread += t_op.seconds();
00099                 if (blocks_per_round > 1) {
00100                     std::cout << "Offset         " << std::setw(8) << offset / MB << " MiB: " << std::fixed;
00101                     std::cout << std::setw(8) << std::setprecision(3) << throughput(block_size, t_op.seconds()) << " MiB/s read";
00102                     std::cout << std::endl;
00103                 }
00104             }
00105 
00106             // truncate
00107             input_file.set_size(r * blocks_per_round * block_size);
00108 
00109             t_read.stop();
00110             totalsizereadchunk += blocks_per_round * block_size;
00111             totaltimereadchunk += t_read.seconds();
00112 
00113             // write the chunk
00114             timer t_write(true);
00115             for (stxxl::unsigned_type i = blocks_per_round; i-- > 0; )
00116             {
00117                 const uint64 offset = (r * blocks_per_round + i) * block_size;
00118                 timer t_op(true);
00119                 // write a block
00120                 {
00121                     char cfn[4096]; // PATH_MAX
00122                     snprintf(cfn, sizeof(cfn), "%s_%012llX", filebase, offset);
00123                     file_type chunk_file(cfn, file::CREAT | file::RDWR | file::DIRECT, 0);
00124                     chunk_file.awrite(buffer + i * block_size, 0, block_size, stxxl::default_completion_handler())->wait();
00125                 }
00126                 t_op.stop();
00127                 totalsizewrite += block_size;
00128                 totaltimewrite += t_op.seconds();
00129                 if (blocks_per_round > 1) {
00130                     std::cout << "Offset         " << std::setw(8) << offset / MB << " MiB: " << std::fixed;
00131                     std::cout << std::setw(8) << std::setprecision(3) << "" << "             ";
00132                     std::cout << std::setw(8) << std::setprecision(3) << throughput(block_size, t_op.seconds()) << " MiB/s write";
00133                     std::cout << std::endl;
00134                 }
00135             }
00136             t_write.stop();
00137             totalsizewritechunk += blocks_per_round * block_size;
00138             totaltimewritechunk += t_write.seconds();
00139 
00140             const uint64 offset = r * blocks_per_round * block_size;
00141             std::cout << "Input offset   " << std::setw(8) << offset / MB << " MiB: " << std::fixed;
00142             std::cout << std::setw(8) << std::setprecision(3) << throughput(block_size * blocks_per_round, t_read.seconds()) << " MiB/s read, ";
00143             std::cout << std::setw(8) << std::setprecision(3) << throughput(block_size * blocks_per_round, t_write.seconds()) << " MiB/s write";
00144             std::cout << std::endl;
00145         }
00146     }
00147     catch (const std::exception & ex)
00148     {
00149         std::cout << std::endl;
00150         STXXL_ERRMSG(ex.what());
00151     }
00152     t_total.stop();
00153 
00154     const int ndisks = 1;
00155 
00156     std::cout << "=============================================================================================" << std::endl;
00157     std::cout << "# Average over " << std::setw(8) << stxxl::STXXL_MAX(totalsizewrite, totalsizeread) / MB << " MiB: ";
00158     std::cout << std::setw(8) << std::setprecision(3) << (throughput(totalsizeread, totaltimeread)) << " MiB/s read, ";
00159     std::cout << std::setw(8) << std::setprecision(3) << (throughput(totalsizewrite, totaltimewrite)) << " MiB/s write" << std::endl;
00160     if (totaltimeread != 0.0)
00161         std::cout << "# Read time    " << std::setw(8) << std::setprecision(3) << totaltimeread << " s" << std::endl;
00162     if (totaltimereadchunk != 0.0)
00163         std::cout << "# ChRd/trnk ti " << std::setw(8) << std::setprecision(3) << totaltimereadchunk << " s" << std::endl;
00164     if (totaltimewrite != 0.0)
00165         std::cout << "# Write time   " << std::setw(8) << std::setprecision(3) << totaltimewrite << " s" << std::endl;
00166     if (totaltimewritechunk != 0.0)
00167         std::cout << "# ChWrite time " << std::setw(8) << std::setprecision(3) << totaltimewritechunk << " s" << std::endl;
00168     std::cout << "# Non-I/O time " << std::setw(8) << std::setprecision(3) << (t_total.seconds() - totaltimewrite - totaltimeread) << " s, average throughput "
00169               << std::setw(8) << std::setprecision(3) << (throughput(totalsizewrite + totalsizeread, t_total.seconds() - totaltimewrite - totaltimeread) * ndisks) << " MiB/s"
00170               << std::endl;
00171     std::cout << "# Total time   " << std::setw(8) << std::setprecision(3) << t_total.seconds() << " s, average throughput "
00172               << std::setw(8) << std::setprecision(3) << (throughput(totalsizewrite + totalsizeread, t_total.seconds()) * ndisks) << " MiB/s"
00173               << std::endl;
00174 
00175     stxxl::aligned_dealloc<BLOCK_ALIGN>(buffer);
00176 
00177     return 0;
00178 }
00179 
00180 // vim: et:ts=4:sw=4
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines