在python中延迟执行大数据

时间:2010-01-05 22:43:51

标签: python cassandra

我正在考虑Python API如何寻找像Cassandra这样的大型数据存储区。 R,Matlab和NumPy倾向于使用“一切都是矩阵”的公式并分别执行每个操作。该模型已证明对于可以适合内存的数据有效。但是,SAS对大数据的好处之一是它逐行执行,在移动到下一行之前执行所有行计算。对于像Cassandra这样的数据存储区,这个模型似乎是一个巨大的胜利 - 我们只循环数据一次。

在Python中,SAS的方法可能类似于:

with load('datastore') as data:
  for row in rows(data):
    row.logincome = row.log(income)
    row.rich = "Rich" if row.income > 100000 else "Poor"

这是(太?)显式,但具有仅循环一次的优点。对于较小的数据集,与NumPy相比,性能将非常差,因为函数不使用编译代码进行矢量化。在R / Numpy中,我们将更简洁和编译:

data.logincome = log(data.income)
data.rich = ifelse(data.income > 100000, "Rich", Poor")

这将非常快速地执行,因为logifelse都是在向量上运算符的编译函数。然而,缺点是我们将循环两次。对于小数据集,这无关紧要,但对于Cassandra支持的数据存储,我不知道这种方法是如何工作的。

问题:有没有办法保留第二个API(如R / Numpy / Matlab),但延迟计算。也许通过最后调用同步(数据)功能?

其他想法?保持NumPy类型语法会很好,因为用户将使用NumPy进行较小的操作,并且可以直观地掌握它的工作原理。

2 个答案:

答案 0 :(得分:2)

我对Cassandra / NumPy一无所知,但是如果你调整你的第二种方法(使用NumPy)以合理大小的块处理数据,你可能会受益于CPU和/或文件系统缓存,因此阻止任何数据循环两次导致的速度减慢,而不会放弃使用优化处理函数的好处。

答案 1 :(得分:1)

我没有一个完美的答案,只是一个粗略的想法,但也许这是值得的。它以Python生成器为中心,采用生产者 - 消费者风格组合。

首先,因为你不想循环两次,我认为没有办法围绕行的显式循环,如下所示:

for row in rows(data):
    # do stuff with row

现在,将行提供给(任意数量的)消费者,这些消费者不会再次阻塞生成器。但是你将使用生成器的send方法。作为此类消费者的示例,这里是riches

的草图
def riches():
    rich_data = []
    while True:
        row = (yield)
        if row == None: break
        rich_data.append("Rich" if row.income > 100000 else "Poor")
    yield rich_data

第一个产量(表达式)只是为了将各行加入riches。它做了它的事情,在这里建立一个结果数组。在while循环之后,第二个yield(语句)用于实际向调用者提供结果数据。

回到调用者循环,它可能看起来像这样:

richConsumer = riches()
richConsumer.next()  # advance to first yield
for row in rows(data):
    richConsumer.send(row)
    # other consumers.send(row) here
richConsumer.send(None)  # make consumer exit its inner loop
data.rich = richConsumer.next() # collect result data

我没有测试过那段代码,但这就是我对它的看法。它没有基于矢量的函数的紧凑语法。但它使主循环非常简单,并将所有处理封装在不同的消费者中。额外的消费者可以很好地堆叠在一起。并且可以通过推动生成器管理代码来进一步抛光API。对象边界。 HTH