2010年02月08日

原创 google.sparsetable 实现细节

goolge.sparse*系列容器依赖关系:- sparsetable   - sparsehashtable      - sparse_hash_map      - sparse_hash_set与现有的一些“标准”实现不同,sparsehash table 使用二次探测法,而不是链接,来解决hash冲突。sparse table 就更奇特了,它是一个两级结构,第一级使用直接索引法,而第二级使用的是顺序查找 。不过,第二级的尺寸比较小,可以放入cpucache,并且它的顺序查找使用的是popcount(bitmap[i]=count of (j sparsetable::operator[i]是这样执行的:阅读全文>

发表于 @ 2010年02月08日 12:39:00 | 评论( loading... ) | 编辑| 举报| 收藏

2010年02月07日

原创 gcc 4.5


只拣一些有用的:

The -fshow-column option is now on by default. This means error messages now have a column associated with them.

A new built-in function __builtin_unreachable() has been added that tells the compiler that control will never reach that point. It may be used after asm statements that terminate by transferring control elsewhere, and in other places that are known to be unreachable.

-Wlogical-op option now warns for l阅读全文>

发表于 @ 2010年02月07日 12:07:00 | 评论( loading... ) | 编辑| 举报| 收藏

2010年02月06日

原创 终于可以优雅的捕获 shell heredoc 内容了

Shell代码 eval 'var=`cat`'  
   终于可以用这种方式捕获 heredoc 的内容了  
   我太高兴了!  
   原先那种方式:  
var=`cat 
     heredoc content  
EOF2  
`  
   不光麻烦,而且会出问题,如果正文中出现一个未被引号引起来的`就挂了  
   用 $(cat ...) 的方式也一样不好  
+EOF  

echo "$var"   eval 'var=`cat`' 阅读全文>

发表于 @ 2010年02月06日 14:29:00 | 评论( loading... ) | 编辑| 举报| 收藏

2010年02月05日

原创 shell heredoc 微妙之处

here doc 的一般用法:[cmd] here-document delimiter可以把 heredoc 的内容放进文件,也可以放进 shell 变量,参见以下代码:#!/bin/sh # write heredoc text to file cat > file 使用`` 捕获 heredoc 内容比较丑陋,但这是我目前能找到的不需要中间文件就可以将heredoc内容存到变量中的唯一方式($(..)也可以,但似乎更丑陋,并且移植性更差)。我觉得比较好的捕获heredoc内容的方式应该象这样,不需要在delimiter 之后再放一个标记:阅读全文>

发表于 @ 2010年02月05日 18:34:00 | 评论( loading... ) | 编辑| 举报| 收藏

原创 通过管道向 hadoop put 文件



使用 hadoop file shell 可以方便地向 hdfs put 文件,但是,该 shell 不支持从管道读取数据并放到 hdfs 文件中。它仅支持这样的 put 命令:Shell 代码 cd $HADOOP_HOME  bin/hadoop fs -put localfile $hdfsFile  bin/hadoop fs -put localfiles $hdfsDir  cd $HADOOP_HOME bin/hadoop fs -put localfile $hdfsFile bin/hadoop fs -put localfiles $hdfsDir
 幸好,主流的 unix (linux,bsd等)都有一个 /dev/fd/ 目录,可以用它实现从管道 put 文件Shell代码 cd $HADOOP_HOME  if bin/hadoop fs -test -d $hdfsFile  then      echo "$hdfsFile is a directory" >&2      exit 1  fi  cat l阅读全文>

发表于 @ 2010年02月05日 15:56:00 | 评论( loading... ) | 编辑| 举报| 收藏

原创 shell 中验证管道是否正确执行



象这样的 shell 代码:
prog1 | prog2 | prog3 | prog4

prog1 | prog2 | prog3 | prog4
$? 只能得到最后一个命令的返回值,该 如何检查整个命令是否全部正确执行?
有一个数组变量PIPESTATUS ,保存了最近一个管道命令中所有子命令的返回值
该返回值与 $? 一样,每次命令都会改写它,因此,要保存它就必须马上!
以下代码可以检查管道命令:prog1 | prog2 | prog3 | prog4 if [[ "0 0 0 0" == ${PIPESTATUS[*]} ]] then echo success else echo failed >&2 fiprog1 | prog2 | prog3 | prog4 if [[ "0 0 0 0" == ${PIPESTATUS[*]} ]] then echo success else echo fai阅读全文>

发表于 @ 2010年02月05日 15:53:00 | 评论( loading... ) | 编辑| 举报| 收藏

原创 my PipelineProcessor



刚看到,intel tbb::pipeline 实现的功能,和我以前实现的一个pipeline : febird::thread::PipelineProcessor ,介绍:
1. 多线程的 pipeline 设计模式
2. 多线程 Pipeline 的改进

几乎就是同一个东西:多线程流水线执行,按次序,stage划分……
可惜啊,它只在我的几个程序中用过,现在有了tbb,它还没来得及壮大就得夭折了。

聊以自慰:
    1. 英雄所见略同
    2. 这个轮子很有价值
    3. 发明轮子之前,先多看看
    4. 多看看,碰到问题就免得发明轮子阅读全文>

发表于 @ 2010年02月05日 15:52:00 | 评论( loading... ) | 编辑| 举报| 收藏

原创 简单的代码生成器创建领域语言


有一类问题,代码模板相同,但有少部分地方不同,一般可以写一个复杂的程序,使用不同的选项,完成不同的任务。或者,把公共的部分抽象成一个代码库,然后在不同程序中引用。但是,如果公共的部分很少,并且比较“专用”,或者因为其它原因,比较难以部署。怎么办?
实际上,有另一种完全不同的编程模式来实现:代码生成器。unix世界中最知名的代码生成器莫过于lex和yacc了。但是,不比每个代码生成器都那么复杂,比如这个代码生成器就非常简单,它只是简单地转换行记录:
 #! /bin/sh field_seperator="||" output=b while getopts :F:vo: arg do case $arg in F ) field_seperator=$OPTARG;; v ) ;; o ) output=$OPTARG;; : ) echo "$0: missing arg for -$OPTARG " >&2 exit;; \?阅读全文>

发表于 @ 2010年02月05日 15:46:00 | 评论( loading... ) | 编辑| 举报| 收藏

原创 LC_ALL=en_US.UTF-8 让 awk 慢了 40 倍!


   无意中发现,在一台服务器上,非常简单的awk程序,比C的等价物要慢40倍,感觉有点不太正常,还以为的确是awk太慢。不得其解,到另一台服务上试 了一下,相同的 awk 程序,相同的测试数据,这台服务器的速度与C相当,也就是说,同样是awk,两台机器速度差了 40 倍,而两台机器配置基本相当。非常困惑,找了两小时的原因,终于发现gawk手册 里面有一段话:
For other single-character record separators, using ‘LC_ALL=C ’ will give you much better performance when reading records. Otherwise, gawk has to make several function calls, per input character to find the record terminator.
在看两台机器的 locale,结果发现,慢的机器上:
[root@slow-server]# local阅读全文>

发表于 @ 2010年02月05日 15:44:00 | 评论( loading... ) | 编辑| 举报| 收藏

原创 count, sum, avg by range in log(n) time


考虑一下这样一个查询:
select count(*), sum(tax), avg(weight)
  from pepole
where id >= ${minid} && id

怎样才能实现更小的时间复杂度?

一般情况下,最简单的方法就是遍历这个区间。但是这需要O(logn +m)的时间复杂度,其中m是区间长度,n是总记录数。

实际上,可以略增一点存储代价,对该查询实现O(logn)的时间复杂度。我以前写过一篇文章 ,可以对count(*)实现logn复杂度:
  count(*, minid, maxid) = rank(maxid) - rank(minid)
其中,rank(id) 表示该记录在整个表中的序号(排序名词)。这很容易理解。

如果要计算sum(x)或avg(x),需要扩张一下,在每个结点中存储一个隐藏值,用来表示该以结点为根的子树的sum(x)值,那么,插入/删除/修改的代价也是O阅读全文>

发表于 @ 2010年02月05日 15:40:00 | 评论( loading... ) | 编辑| 举报| 收藏

原创 MapReduce应该做更少的事情


MapReduce 做的事情太多了。相比 unix 思想,它更多的是提供了一种策略(Policy),而非一种机制(Machanism)。
对于并行计算,如果我仅仅需要一种机制,暂且把这种机制叫做S,那么S只需要提供:任意切分原始输入  ——split无依赖的计算    ——map按依赖切分中间结果 ——partition有依赖的计算    ——reduce容错        ——MR 矩阵(包括数据)
MapReduce当然提供了这个机制,只是,以它自己特定的方式(Policy)提供——就是排序。
Map 阶段是无依赖的计算,Reduce是有依赖的计算。Map的输入集合可以是任意顺序,任意切分,Combine可以看作只是为了提升效率而提前解决局部(local)依赖。
Reduce用来解决依赖,这个依赖,是按照Key的依赖,相同的Key和它的Value集合,是一个依赖集。
MapReduce 使用先排序,然后把整个Key-ValueList发送给应用接口,解决了这个问题。这样做,应用代码可以极大简化。但是,同时,这也严重地限制阅读全文>

发表于 @ 2010年02月05日 15:38:00 | 评论( loading... ) | 编辑| 举报| 收藏

原创 字符串基数排序


  对字符串使用基数排序,以前,我一直觉得:因为字符串的长度不一,无法使用基数排序。前两天因为有需要,忽然想通了!即便长短不一,也可以使用链式基数排序!
  首先,将字符串长度当作最低有效位,因为基数排序是从最低有效位开始排的,就先用分配-收集算法对长度做一趟。对字符串中的具体某一位字符进行排序相比,算法是一样的,只是写法稍有不同。要将排序结果的lenRadix指针保存起来,后面要用。
  接下来,从lenRadix中取字符串最长的那个sublist,对该sublist排序,然后将这一趟的结果first保存起来,连接到长度次短的那个sublist之后,然后对这两个链接起来的列表进行一趟分配-收集。如此,直到最高有效位。
  所有的工作就做完了,根据此算法,对所有待排序字符串中的每个字符,均需要一次且仅一次访问!另外,还需要 O((radix+1)*max_str_len)的时间复杂度用于扫描链接表,(radix+1)是因为还有一个strlen链接表。所以,总的时间复 杂度是O(n+(radix+1)*max_str_len),其中N是所有字阅读全文>

发表于 @ 2010年02月05日 15:36:00 | 评论( loading... ) | 编辑| 举报| 收藏

原创 MultipleInputs/MultipleOutpus


仔细看了一下 Hadoop.MapReduce 的代码,发现了两个新类:MultipleInputs/MultipleOutpus,再仔细看它们的详细文档,的确实现了我想要的功能 :
不同的InputPath,可是使用不同的InputFormat 和 Mapper
可以将不同类型(可能是多种计算)的结果写入不同的Reduce Output。

再看一下它们的实现代码,让我大失所望,MultipleInput 还行,没有白白折损效率的地方,MultipleOutput就太让我大跌眼镜了!简单的写一条记录出去,白白做的额外工作的耗时,可以写30条记录了。

多了解MapReduce的整体实现,可以考虑自己做一个更高效的MultiOutput。
阅读全文>

发表于 @ 2010年02月05日 15:27:00 | 评论( loading... ) | 编辑| 举报| 收藏

2009年11月03日

原创 内嵌变长数据结构范例——trbstrmap

以前的这篇文章介绍了嵌入的变长数据结构(embeded)本文介绍一个使用这种思想实现的通用strmap容器,相当于:std::map。实现上使用了我以前写的线索红黑树——相比标准map的实现,节省了一半的结点存储开销,而平均查找时间只付出很小的额外开销,并且没有代码膨胀问题。 使用大多数情况下trbstrmap // Compare是可选的,allocator 总在类范围,可以修改:trbstrmap::s_vtab.alloc = ....;为了节省空间,trbstrmap使用一个字节存储strkey_length,因此,strlen(strkey)不可超过255,允许长度为0的key。最大长度255基本上可以应对绝大多数情况。把key作为变长字段,有一个原因很重要:key一旦阅读全文>

发表于 @ 2009年11月03日 22:13:00 | 评论( loading... ) | 编辑| 举报| 收藏

2009年10月27日

原创 MapReduce做了多余的事情

MapReduce做了多余的事情
本文假定读者已了解MapReduce。Map
Map阶段一般做三件事情:
1.         切分输入
2.         变换输入为输出
3.         执行可选的Combine
如果要说哪项是多于的,大概就是Combine了。Combine在很多时候可以减少传递给Reduce的数据量;但是,也有一些时候,Combine只是空耗时间:
1.         Map输入中重复Key很多时,Combine会提高性能
2.         Map输入中重复Key很少时,Combine会降低性能
3.         网络速度很快时,Combine提高的性能有限,甚至不会提高性能
作为总结:用不用Combine,一方面取决于数据的特征(重复Key的多寡);另一方面就是网络带宽。Reduce
以下ReduceCallback指应用程序定义的Reduce回调函数。

在Reduce阶段,传统上,Reduce阶段做三件事情:阅读全文>

发表于 @ 2009年10月27日 15:25:00 | 评论( loading... ) | 编辑| 举报| 收藏

Copyright © whinah
Powered by CSDN Blog