隐藏中间变量
Stream 是流处理的意思,我一直觉得这是一个非常显然的事情。数据流不就是像流水线一样吗,一道工序一道工序的配合,然后完成工作。常规的数据处理,也是得一点点干呀。比如说对数组 a[N]
中的每个元素求平方和,如果用常规数据处理来写:
int sum = 0;
for (int i = 0; i < N; i++) {
tmp = a[i] * a[i];
sum += tmp;
}
如果用数据流来写:
int sum = a.power(2).sum()
这种方式似乎和上面没啥区别。当然这种观念是错误的。流处理的优势在于 隐藏了不必要的中间变量 ,从而使得计算过程更加本质。
还是以上述方法为例,在逻辑上这两个计算过程并没有任何区别,都是将数组中的元素先平方,然后累加。但是在实现上,常规的数据处理“写死了”很多东西,如果以更加硬件的视角来看,它其实是:
load r1, a[i]
load r2, a[i]
mul r3, r1, r2
add r4, r4, r3
其中 r1, r2, r3
都是中间的中间变量,而难道计算一定需要这种形式吗?有没有可能采用别的中间变量,或者完全不采用“显式”的临时变量。比如说硬件中的脉动阵列,就是一种没有显式中间变量的设计。
而数据流的写法就不会有这些问题,没有显式的中间变量。
顺序访存
此外,“流”的概念还意味着“顺序访存”,也就是必须是“一个个按顺序处理元素”的语义。那么这种顺序访问如果被硬件特性或者编译器利用,那么也会很有效果。
因为传统的图灵机,是随机访问的。
异步
此外,“流”的概念往往还意味着“异步”,因为流存在 source 和 sink 的概念,这两者就像 Pipe 的读写指针一样,可以按照不同的速度去移动,所以就有了异步的概念。