Stxxl
1.4.0
|
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