隐藏中间变量

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 的读写指针一样,可以按照不同的速度去移动,所以就有了异步的概念。