STXXL  1.4.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
async_schedule.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  * lib/algo/async_schedule.cpp
3  *
4  * Part of the STXXL. See http://stxxl.sourceforge.net
5  *
6  * Copyright (C) 2002, 2009 Roman Dementiev <[email protected]>
7  * Copyright (C) 2009, 2010 Andreas Beckmann <[email protected]>
8  *
9  * Distributed under the Boost Software License, Version 1.0.
10  * (See accompanying file LICENSE_1_0.txt or copy at
11  * http://www.boost.org/LICENSE_1_0.txt)
12  **************************************************************************/
13 
14 // Implements the "prudent prefetching" as described in
15 // D. Hutchinson, P. Sanders, J. S. Vitter: Duality between prefetching
16 // and queued writing on parallel disks, 2005
17 // DOI: 10.1137/S0097539703431573
18 
19 
22 #include <stxxl/bits/io/file.h>
23 #include <stxxl/bits/namespace.h>
24 #include <stxxl/bits/parallel.h>
25 #include <stxxl/bits/unused.h>
26 #include <stxxl/bits/verbose.h>
27 
28 #include <algorithm>
29 #include <cassert>
30 #include <functional>
31 #include <queue>
32 #include <utility>
33 #include <vector>
34 
35 
37 
38 namespace async_schedule_local {
39 
40 // only one type of event: WRITE COMPLETED
41 struct sim_event
42 {
44  int_type iblock;
45  inline sim_event(int_type t, int_type b) : timestamp(t), iblock(b) { }
46 };
47 
48 struct sim_event_cmp : public std::binary_function<sim_event, sim_event, bool>
49 {
50  inline bool operator () (const sim_event& a, const sim_event& b) const
51  {
52  return a.timestamp > b.timestamp;
53  }
54 };
55 
56 typedef std::pair<int_type, int_type> write_time_pair;
57 struct write_time_cmp : public std::binary_function<write_time_pair, write_time_pair, bool>
58 {
59  inline bool operator () (const write_time_pair& a, const write_time_pair& b) const
60  {
61  return a.second > b.second;
62  }
63 };
64 
65 
66 static inline int_type get_disk(int_type i, const int_type* disks, int_type D)
67 {
68  int_type disk = disks[i];
69  if (disk == file::NO_ALLOCATOR)
70  disk = D; // remap to sentinel
71  assert(0 <= disk && disk <= D);
72  return disk;
73 }
74 
76  const int_type* disks,
77  const int_type L,
78  const int_type m_init,
79  const int_type D,
80  std::pair<int_type, int_type>* o_time)
81 {
82  typedef std::priority_queue<sim_event, std::vector<sim_event>, sim_event_cmp> event_queue_type;
83  typedef std::queue<int_type> disk_queue_type;
84  assert(L >= D);
85  disk_queue_type* disk_queues = new disk_queue_type[D + 1]; // + sentinel for remapping NO_ALLOCATOR
86  event_queue_type event_queue;
87 
88  int_type m = m_init;
89  int_type i = L - 1;
90  int_type oldtime = 0;
91  bool* disk_busy = new bool[D + 1];
92 
93  while (m && (i >= 0))
94  {
95  int_type disk = get_disk(i, disks, D);
96  disk_queues[disk].push(i);
97  i--;
98  m--;
99  }
100 
101  for (int_type ii = 0; ii <= D; ii++)
102  if (!disk_queues[ii].empty())
103  {
104  int_type j = disk_queues[ii].front();
105  disk_queues[ii].pop();
106  event_queue.push(sim_event(1, j));
107  //STXXL_MSG("Block "<<j<<" scheduled");
108  }
109 
110  while (!event_queue.empty())
111  {
112  sim_event cur = event_queue.top();
113  event_queue.pop();
114  if (oldtime != cur.timestamp)
115  {
116  // clear disk_busy
117  for (int_type i = 0; i <= D; i++)
118  disk_busy[i] = false;
119 
120  oldtime = cur.timestamp;
121  }
122 
123 
124  STXXL_VERBOSE1("Block " << cur.iblock << " put out, time " << cur.timestamp << " disk: " << disks[cur.iblock]);
125  o_time[cur.iblock] = std::pair<int_type, int_type>(cur.iblock, cur.timestamp);
126 
127  if (i >= 0)
128  {
129  int_type disk = get_disk(i, disks, D);
130  if (disk_busy[disk])
131  {
132  disk_queues[disk].push(i--);
133  }
134  else
135  {
136  if (!disk_queues[disk].empty())
137  {
138  STXXL_VERBOSE1("c Block " << disk_queues[disk].front() << " scheduled for time " << cur.timestamp + 1);
139  event_queue.push(sim_event(cur.timestamp + 1, disk_queues[disk].front()));
140  disk_queues[disk].pop();
141  }
142  else
143  {
144  STXXL_VERBOSE1("a Block " << i << " scheduled for time " << cur.timestamp + 1);
145  event_queue.push(sim_event(cur.timestamp + 1, i--));
146  }
147  disk_busy[disk] = true;
148  }
149  }
150 
151  // add next block to write
152  int_type disk = get_disk(cur.iblock, disks, D);
153  if (!disk_busy[disk] && !disk_queues[disk].empty())
154  {
155  STXXL_VERBOSE1("b Block " << disk_queues[disk].front() << " scheduled for time " << cur.timestamp + 1);
156  event_queue.push(sim_event(cur.timestamp + 1, disk_queues[disk].front()));
157  disk_queues[disk].pop();
158  disk_busy[disk] = true;
159  }
160  }
161 
162  assert(i == -1);
163  for (int_type i = 0; i <= D; i++)
164  assert(disk_queues[i].empty());
165 
166 
167  delete[] disk_busy;
168  delete[] disk_queues;
169 
170  return (oldtime - 1);
171 }
172 
173 } // namespace async_schedule_local
174 
175 
177  const int_type* first,
178  const int_type* last,
179  int_type* out_first,
180  int_type m,
181  int_type D)
182 {
183  typedef std::pair<int_type, int_type> pair_type;
184  int_type L = last - first;
185  if (L <= D)
186  {
187  for (int_type i = 0; i < L; ++i)
188  out_first[i] = i;
189 
190  return;
191  }
192  pair_type* write_order = new pair_type[L];
193 
194  int_type w_steps = async_schedule_local::simulate_async_write(first, L, m, D, write_order);
195 
196  STXXL_VERBOSE1("Write steps: " << w_steps);
197 
198  for (int_type i = 0; i < L; i++)
199  STXXL_VERBOSE1(first[i] << " " << write_order[i].first << " " << write_order[i].second);
200 
201  std::stable_sort(write_order, write_order + L, async_schedule_local::write_time_cmp() _STXXL_FORCE_SEQUENTIAL);
202 
203  for (int_type i = 0; i < L; i++)
204  {
205  out_first[i] = write_order[i].first;
206  //if(out_first[i] != i)
207  STXXL_VERBOSE1(i << " " << out_first[i]);
208  }
209 
210  delete[] write_order;
211  STXXL_UNUSED(w_steps);
212 }
213 
215 
216 // vim: et:ts=4:sw=4
std::pair< int_type, int_type > write_time_pair
Encapsulates disk queues.
Definition: disk_queues.h:34
static int_type get_disk(int_type i, const int_type *disks, int_type D)
double timestamp()
Returns number of seconds since the epoch, high resolution.
Definition: timer.h:42
choose_int_types< my_pointer_size >::int_type int_type
Definition: types.h:66
#define STXXL_BEGIN_NAMESPACE
Definition: namespace.h:16
void STXXL_UNUSED(const U &)
Definition: unused.h:23
#define STXXL_VERBOSE1(x)
Definition: verbose.h:99
int_type simulate_async_write(const int_type *disks, const int_type L, const int_type m_init, const int_type D, std::pair< int_type, int_type > *o_time)
void compute_prefetch_schedule(const int_type *first, const int_type *last, int_type *out_first, int_type m, int_type D)
#define _STXXL_FORCE_SEQUENTIAL
Definition: parallel.h:51
#define STXXL_END_NAMESPACE
Definition: namespace.h:17