假设我们有一个必须由一组工作人员处理的文本(map / reduce项目中的映射器):文本的每个部分(拆分)必须一致(没有单词可以在两个工人之间分开)并且分裂的大小应该尽可能相等(负载平衡)。
这是我的算法:
off_t begin
和off_t end
(文本中的起始和结束字节)组成。输入(文字长度= 29个字符):
Hello Darkness my old friend
第1阶段有4名工人(〜=每名工人7个字符):
|Hello D|arkness| my old| friend|
阶段2:
|Hello Darkness| |my old |friend|
这是每次拆分的第2阶段代码:
ifstream ifs (file , ifstream::in);
char c;
string s;
if(begin>0){//begin=0 then first split: cannot break a word!
//if char before the first one is different from ' ' or '\n'
//then the split begins in the middle of a word (bad)
ifs.seekg(begin-1,ios::beg);
ifs.get(c);
if(c!=' ' && c!='\n'){
getline(ifs,s,' '); //jump to the next white space
begin+=s.length();
}
if(begin>end)
end=begin;
}
ifs.seekg(end,ios::beg);
ifs.get(c);
if(c!=' ' && c!='\n' && end != size){
getline(ifs,s,' ');
end+=s.length();
}
如您所见,此解决方案有两个问题:
您是否有任何改进解决方案的建议(在优雅和/或性能方面)?
答案 0 :(得分:0)
我认为在算法上,你不能做得更好(如果你正在做Map | Reduce你可能有 lot 的数据,所以差别很小)。将分组排列为Hello| Darkness| my old| friend
的工作将会过度。
略有改善可能是:
唯一的麻烦是这会使代码甚至更多复杂。
答案 1 :(得分:0)
你也可以向后检查并使用较少的字符,直到空格。但是,这会导致额外的复杂性。对于这个简单的情况,它并不重要,因为我希望这些小部件的处理速度如此之快,以至于没有任何明显的差异。
随着分割的大小增加(比如说500个字符甚至一个兆字节),如果单词会保持相对较短,那么不平衡将变得越来越不重要 - 所以我也不会打扰,我会"保持简单,愚蠢" (KISS)。