+ /* More efficient (?) work sharing algorithm: a job (i,j) is initially assigned twice: to proc#i and to proc#j.
+ * Then try to reduce as much as possible the variance of the num of jobs per proc:
+ * - take the most loaded proc i,
+ * + select the job (i,j) for which proc#j is the less loaded
+ * + remove this job from proc#i
+ * - repeat until no more duplicates are found
+ */
+ void OverlapElementLocator::computeTodoList_new()
+ {
+ using namespace std;
+ int infinity = std::numeric_limits<int>::max();
+ // Initialisation
+ int grp_size = _group.size();
+ vector < map<ProcCouple, int> > full_set(grp_size );
+ int srcProcID = 0;
+ for(vector< vector< int > >::const_iterator it = _proc_pairs.begin(); it != _proc_pairs.end(); it++, srcProcID++)
+ for (vector< int >::const_iterator it2=(*it).begin(); it2 != (*it).end(); it2++)
+ {
+ // Here a pair of the form (i,i) is added only once!
+ int tgtProcID = *it2;
+ ProcCouple cpl = make_pair(srcProcID, tgtProcID);
+ full_set[srcProcID][cpl] = -1;
+ full_set[tgtProcID][cpl] = -1;
+ }
+ int procID = 0;
+ vector < map<ProcCouple, int> > ::iterator itVector;
+ map<ProcCouple, int>::iterator itMap;
+ for(itVector = full_set.begin(); itVector != full_set.end(); itVector++, procID++)
+ for (itMap=(*itVector).begin(); itMap != (*itVector).end(); itMap++)
+ {
+ const ProcCouple & cpl = (*itMap).first;
+ if (cpl.first == cpl.second)
+ // special case - this couple can not be removed in the future
+ (*itMap).second = infinity;
+ else
+ {
+ if(cpl.first == procID)
+ (*itMap).second = full_set[cpl.second].size();
+ else // cpl.second == srcProcID
+ (*itMap).second = full_set[cpl.first].size();
+ }
+ }
+ INTERP_KERNEL::AutoPtr<bool> proc_valid = new bool[grp_size];
+ fill((bool *)proc_valid, proc_valid+grp_size, true);
+
+ // Now the algo:
+ while (find((bool *)proc_valid, proc_valid+grp_size, true) != proc_valid+grp_size)
+ {
+ // Most loaded proc:
+ int max_sz = -1, max_id = -1;
+ for(itVector = full_set.begin(), procID=0; itVector != full_set.end(); itVector++, procID++)
+ {
+ int sz = (*itVector).size();
+ if (proc_valid[procID] && sz > max_sz)
+ {
+ max_sz = (*itVector).size();
+ max_id = procID;
+ }
+ }
+
+ // Nothing more to do:
+ if (max_sz == -1)
+ break;
+ // For this proc, job with less loaded second proc:
+ int min_sz = infinity;
+ map<ProcCouple, int> & max_map = full_set[max_id];
+ ProcCouple hit_cpl = make_pair(-1,-1);
+ for(itMap=max_map.begin(); itMap != max_map.end(); itMap++)
+ if ((*itMap).second < min_sz)
+ hit_cpl = (*itMap).first;
+ if (hit_cpl.first == -1)
+ {
+ // Plouf. Current proc 'max_id' can not be reduced. Invalid it:
+ proc_valid[max_id] = false;
+ continue;
+ }
+ // Remove item from proc 'max_id'
+ full_set[max_id].erase(hit_cpl);
+ // And mark it as not removable on the other side:
+ if (hit_cpl.first == max_id)
+ full_set[hit_cpl.second][hit_cpl] = infinity;
+ else // hit_cpl.second == max_id
+ full_set[hit_cpl.first][hit_cpl] = infinity;
+
+ // Now update all counts of valid maps:
+ procID = 0;
+ for(itVector = full_set.begin(); itVector != full_set.end(); itVector++, procID++)
+ if(proc_valid[procID] && procID != max_id)
+ for(itMap = (*itVector).begin(); itMap != (*itVector).end(); itMap++)
+ {
+ const ProcCouple & cpl = (*itMap).first;
+ // Unremovable item:
+ if ((*itMap).second == infinity)
+ continue;
+ if (cpl.first == max_id || cpl.second == max_id)
+ (*itMap).second--;
+ }
+ }
+ // Final formatting - extract remaining keys in each map:
+ int myProcId=_group.myRank();
+ _all_todo_lists.resize(grp_size);
+ procID = 0;
+ for(itVector = full_set.begin(); itVector != full_set.end(); itVector++, procID++)
+ for(itMap = (*itVector).begin(); itMap != (*itVector).end(); itMap++)
+ _all_todo_lists[procID].push_back((*itMap).first);
+ _to_do_list=_all_todo_lists[myProcId];
+
+#ifdef DEC_DEBUG
+ std::stringstream scout;
+ scout << "(" << myProcId << ") my TODO list is: ";
+ for (std::vector< ProcCouple >::const_iterator itdbg=_to_do_list.begin(); itdbg!=_to_do_list.end(); itdbg++)
+ scout << "(" << (*itdbg).first << "," << (*itdbg).second << ")";
+ std::cout << scout.str() << "\n";
+#endif
+ }
+
+ void OverlapElementLocator::fillProcToSend()
+ {