BCP_tm_nodes_to_storage.cpp
Go to the documentation of this file.
1 // Copyright (C) 2007, International Business Machines
2 // Corporation and others. All Rights Reserved.
3 
4 #include "BCP_os.hpp"
5 #include "BCP_tm.hpp"
6 #include "BCP_tm_node.hpp"
7 #include "BCP_tm_user.hpp"
8 #include "BCP_tm_functions.hpp"
9 
10 #define NUMNODES_BASED_ON_BUFSIZE
11 
12 //#############################################################################
13 
15  std::vector<BCP_tm_node*>& nodes_to_send,
16  const long bufsize)
17 {
18 #ifndef NUMNODES_BASED_ON_BUFSIZE
19  const size_t send_size = 100;
20 #endif
21  BCP_vec<BCP_tm_node*>& children = node->_children;
22  for (int i = children.size() - 1; i >= 0; --i) {
23  BCP_tm_node* s = children[i];
24  if (s == NULL)
25  continue;
26  if (BCP_tm_scan_children(p, s, nodes_to_send, bufsize))
27  return true;
28  }
29  if (node->_data._desc.IsValid()) {
30  nodes_to_send.push_back(node);
32  p.msg_buf.pack(node->_index);
33  node->_data._desc->pack(p.packer, def, p.msg_buf);
34  bool has_user_data = node->_data._user.IsValid();
35  p.msg_buf.pack(has_user_data);
36  if (has_user_data) {
37  p.packer->pack_user_data(node->_data._user.GetRawPtr(), p.msg_buf);
38  }
39  }
40 #ifndef NUMNODES_BASED_ON_BUFSIZE
41  return (nodes_to_send.size() >= send_size);
42 #else
43  return (p.msg_buf.size() > bufsize);
44 #endif
45 }
46 
47 //#############################################################################
48 
50  std::vector<BCP_tm_node*>& nodes_to_send,
51  const long bufsize)
52 {
53 #ifndef NUMNODES_BASED_ON_BUFSIZE
54  const size_t send_size = 100;
55 #endif
56  if (node->_data._desc.IsValid()) {
57  nodes_to_send.push_back(node);
59  p.msg_buf.pack(node->_index);
60  node->_data._desc->pack(p.packer, def, p.msg_buf);
61  bool has_user_data = node->_data._user.IsValid();
62  p.msg_buf.pack(has_user_data);
63  if (has_user_data) {
64  p.packer->pack_user_data(node->_data._user.GetRawPtr(), p.msg_buf);
65  }
66 #ifndef NUMNODES_BASED_ON_BUFSIZE
67  if (nodes_to_send.size() >= send_size)
68 #else
69  if (p.msg_buf.size() > bufsize)
70 #endif
71  {
72  return true;
73  }
74  }
75  BCP_tm_node* parent = node->_parent;
76  if (parent == NULL)
77  return false;
78  BCP_vec<BCP_tm_node*>& siblings = parent->_children;
79  for (int i = siblings.size() - 1; i >= 0; --i) {
80  BCP_tm_node* s = siblings[i];
81  if (s == node || s == NULL)
82  continue;
83  if (BCP_tm_scan_children(p, s, nodes_to_send, bufsize))
84  return true;
85  }
86  return BCP_tm_scan_siblings(p, parent, nodes_to_send, bufsize);
87 }
88 
89 //#############################################################################
90 
99 {
100  const int maxheap = p.param(BCP_tm_par::MaxHeapSize);
101  if (maxheap == -1) {
102  return true;
103  }
104 #if 0
105  // FIXME--DELETE (used to test Bonmin code)
106  printf("local nodes: %i\n", BCP_tm_node::num_local_nodes);
107  printf("remote nodes: %i\n", BCP_tm_node::num_remote_nodes);
108 #endif
109 // return (BCP_tm_node::num_local_nodes < 10);
110 
111  const double usedheap = BCP_used_heap();
112  if (usedheap == -1)
113  return true;
114  const double freeheap = maxheap - usedheap;
115  printf("free: %f used: %f free/max: %f\n",
116  freeheap, usedheap, freeheap/maxheap);
117  return (freeheap > 1<<24 /* 16M */ && freeheap / maxheap > 0.15);
118 }
119 
120 //#############################################################################
121 
139 {
140  if (! p.need_a_TS)
141  return false;
142 
143  int pid = -1;
144 
145  /* check if any of the TS processes accept data */
146  int max_space = 0;
147  for (std::map<int,int>::const_iterator tsi = p.ts_space.begin();
148  tsi != p.ts_space.end(); ++tsi) {
149  if (tsi->second > max_space) {
150  max_space = tsi->second;
151  pid = tsi->first;
152  }
153  }
154  if (max_space < 1 << 22 /* 4M */) {
155  pid = -1;
156  }
157 
158  BCP_buffer& buf = p.msg_buf;
159 
160  if (pid == -1) {
161  /* None of the TS processes accept data, we need a new one. */
162  if (p.lp_scheduler.maxNodeIds() > 1) {
163  pid = p.lp_scheduler.request_node_id();
164  if (pid == -1) {
165  return true;
166  }
167  std::vector<int>::iterator ipid =
168  std::find(p.lp_procs.begin(), p.lp_procs.end(), pid);
169  if (ipid == p.lp_procs.end()) {
170  throw BCP_fatal_error("\
171 Trying to convert an LP into TS, but its pid is not in lp_procs!\n");
172  }
173  p.lp_procs.erase(ipid);
174  p.ts_procs.push_back(pid);
175  printf("Turning LP (#%i) into a TS\n", pid);
177  }
178  }
179 
180  if (pid == -1)
181  return true;
182 
183  /* OK we can balance */
184 
185  /*
186  FIXME: For now we just balance node data. When we run hybrid (cuts are
187  FIXME: added) then we must balance cuts, too
188  */
189  std::vector<BCP_tm_node*> nodes_to_send;
190  const std::vector<CoinTreeSiblings*>& candList =
191  p.candidate_list.getTree()->getCandidates();
192  BCP_tm_node* node =
193  dynamic_cast<BCP_tm_node*>(candList.back()->currentNode());
194 
195  /* 'node' is a leaf. Starting from it traverse the tree until there is
196  enough data to be sent off. The "enough" means that the message buffer
197  takes up 25% of the free space. */
198  int usedheap = BCP_used_heap();
199  assert(usedheap > 0);
200  const int maxheap = p.param(BCP_tm_par::MaxHeapSize);
201  assert(maxheap > 0);
202  int freeheap = maxheap - usedheap;
203  printf("Before sending off: freeheap: %i usedheap: %i\n",
204  freeheap, usedheap);
205  buf.clear();
206  BCP_tm_scan_siblings(p, node, nodes_to_send, freeheap >> 2);
207  int num = nodes_to_send.size();
208  if (num == 0) {
209  // Everything is already sent out, but we are still having memory problems
210  throw BCP_fatal_error("No memory left in TM\n");
211  }
212  int fake_index = -1;
213  buf.pack(fake_index);
214  p.msg_env->send(pid, BCP_Msg_NodeList, buf);
215  buf.clear();
216  int saved = 0, fm = 0;
217  p.msg_env->receive(pid, BCP_Msg_NodeListReply, buf, -1);
218  buf.unpack(saved);
219  buf.unpack(fm);
220  p.ts_space[pid] = fm;
221  for (int i = 0; i < saved; ++i) {
222  node = nodes_to_send[i];
223  node->_locally_stored = false;
224  node->_data._desc = NULL;
225  node->_data._user = NULL;
226  node->_data_location = pid;
227  }
228  nodes_to_send.clear();
229 
230  usedheap = BCP_used_heap();
231  freeheap = maxheap - usedheap;
232  printf("After sending off: freeheap: %i usedheap: %i\n",
233  freeheap, usedheap);
234 
235  if (saved == 0) {
236  // Something is wrong. The least full TS did not accept anything...
237  // sleep(10000);
238  throw BCP_fatal_error("TS did not accept anything\n");
239  }
240 
243 
244 #if 0
245  // FIXME--DELETE (used to test Bonmin code)
246  for (size_t k = 0; k < p.search_tree.size(); ++k) {
247  BCP_tm_node* n = p.search_tree[k];
248  if (n && n->_locally_stored) {
249  assert(n->_data._desc.IsNull() && n->_data._user.IsNull());
250  }
251  }
252 #endif
253 
254  return false;
255 }
256 
BCP_tree search_tree
Definition: BCP_tm.hpp:239
BCP_buffer msg_buf
members to measure how long it took to process the root node.
Definition: BCP_tm.hpp:183
virtual void send(const int target, const BCP_message_tag tag)=0
Send an empty message (message tag only) to the process given by the frist argument.
BCP_buffer & pack(const T &value)
Pack a single object of type T.
Definition: BCP_buffer.hpp:177
static bool BCP_tm_scan_siblings(BCP_tm_prob &p, BCP_tm_node *node, std::vector< BCP_tm_node * > &nodes_to_send, const long bufsize)
static int num_local_nodes
Definition: BCP_tm_node.hpp:73
void BCP_tm_notify_process_type(BCP_tm_prob &p, BCP_process_t ptype, int num, const int *pids)
BCP_buffer & unpack(T &value)
Unpack a single object of type T.
Definition: BCP_buffer.hpp:186
virtual void receive(const int source, const BCP_message_tag tag, BCP_buffer &buf, const double timeout)=0
Blocking receive with timeout.
Print out a message when the default version of an overridable method is executed.
int maxNodeIds() const
Return the maximum possible number of busy LP processes.
Definition: BCP_process.hpp:99
BCP_vec< BCP_tm_node * > _children
Definition: BCP_tm_node.hpp:87
static int num_remote_nodes
Definition: BCP_tm_node.hpp:74
size_t size() const
bool BCP_tm_is_data_balanced(BCP_tm_prob &p)
This function is invoked from exactly one place, the beginning of BCP_tm_unpack_node_description().
CoinSearchTreeManager candidate_list
Definition: BCP_tm.hpp:243
bool BCP_tm_balance_data(BCP_tm_prob &p)
This function is invoked after data from an LP is unpacked (and only if p.need_a_TS is true)...
void push_back(const_reference x)
Append x to the end of the vector.
bool need_a_TS
Definition: BCP_tm.hpp:234
Coin::SmartPtr< BCP_node_change > _desc
Definition: BCP_tm_node.hpp:53
std::vector< int > ts_procs
members to measure how long it took to process the root node.
Definition: BCP_tm.hpp:185
static long BCP_used_heap()
Definition: BCP_os.hpp:54
NO OLD DOC.
Definition: BCP_tm.hpp:136
BCP_tm_node_data _data
int request_node_id()
Request an id for processing nodes.
void fint fint * k
void fint fint fint fint fint fint fint fint fint fint real real real real real real real real * s
void clear()
Completely clear the buffer.
Definition: BCP_buffer.hpp:168
Coin::SmartPtr< BCP_user_data > _user
Definition: BCP_tm_node.hpp:54
static bool BCP_tm_scan_children(BCP_tm_prob &p, BCP_tm_node *node, std::vector< BCP_tm_node * > &nodes_to_send, const long bufsize)
Currently there isn&#39;t any error handling in BCP.
Definition: BCP_error.hpp:20
BCP_tm_node * _parent
Definition: BCP_tm_node.hpp:82
BCP_message_environment * msg_env
A class that holds the methods about how to pack things.
Definition: BCP_tm.hpp:156
BCP_user_pack * packer
A class that holds the methods about how to pack things.
Definition: BCP_tm.hpp:153
The maximum size of the memory heap the TM can use.
size_t size() const
Return the current number of entries.
Definition: BCP_vector.hpp:116
std::vector< int > lp_procs
members to measure how long it took to process the root node.
Definition: BCP_tm.hpp:186
This class describes the message buffer used for all processes of BCP.
Definition: BCP_buffer.hpp:39
BCP_scheduler lp_scheduler
members to measure how long it took to process the root node.
Definition: BCP_tm.hpp:188
std::map< int, int > ts_space
Definition: BCP_tm.hpp:235
virtual void pack_user_data(const BCP_user_data *ud, BCP_buffer &buf)
Pack an user data.
Definition: BCP_USER.hpp:119
void fint * n
char param(BCP_tm_par::chr_params key) const
Definition: BCP_tm.hpp:298
int size() const
Return the size of the current message in the buffer.
Definition: BCP_buffer.hpp:95