首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Quantopian / Zipline:管道包装中的奇怪图案

Quantopian / Zipline:管道包装中的奇怪图案
EN

Stack Overflow用户
提问于 2016-05-24 06:33:33
回答 1查看 298关注 0票数 1

最近,我在Quantopian/Zipline的“管道”API中发现了一个非常奇怪的模式:它们有一个CustomFactor类,在这个类中,您将发现在实现您自己的因子模型时,compute()方法将被覆盖。

compute()的签名是:def compute(self, today, assets, out, *inputs),参数“out”的注释如下:

输出与assets形状相同的数组。compute应该将其所需的返回值写入out

当我问函数为什么不能简单地返回输出数组而不是写入输入参数时,我收到了以下答复:

“如果API要求compute()返回输出数组,我们最终会将数组复制到实际的输出缓冲区中,这意味着额外的副本将不必要地生成。”

我不明白他们为什么要这么做..。显然,在Python中,不存在按值传递的问题,也没有不必要地复制数据的风险。这真的很痛苦,因为这是他们推荐给人们编写代码的那种实现:

代码语言:javascript
复制
    def compute(self, today, assets, out, data):
       out[:] = data[-1]

所以我的问题是,为什么不简单地:

代码语言:javascript
复制
    def compute(self, today, assets, data):
       return data[-1]
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-05-24 15:50:20

(我在这里设计和实现了这个API。)

您是对的,Python对象在传入和输出函数时不会被复制。从CustomFactor中返回一行与将值写入提供的数组之间存在差异的原因与在调用您的CustomFactor计算方法的代码中创建的副本有关。

最初设计CustomFactor API时,调用计算方法的代码大致如下所示:

代码语言:javascript
复制
def _compute(self, windows, dates, assets):
    # `windows` here is list of iterators yielding 2D slices of 
    # the user's requested inputs

    # `dates` and `assets` are row/column labels for the final output.

    # Allocate a (dates x assets) output array.
    # Each invocation of the user's `compute` function
    # corresponds to one row of output.
    output = allocate_output()

    for i in range(len(dates)):

        # Grab the next set of input arrays.
        inputs = [next(w) for w in windows]

        # Call the user's compute, which is responsible for writing
        # values into `out`.
        self.compute(
            dates[i], 
            assets,
            # This index is a non-copying operation.
            # It creates a view into row `i` of `output`.
            output[i],
            *inputs  # Unpack all the inputs.
        )

    return output

这里的基本思想是,我们已经预取了大量的数据,现在我们将遍历窗口进入该数据,调用用户对数据的计算函数,并将结果写入预先分配的输出数组,然后传递到进一步的转换中。

无论我们做什么,我们都必须支付至少一个副本的成本,才能将用户的compute函数的结果输入输出数组。

正如您所指出的,最明显的API是让用户只返回输出行,在这种情况下调用代码如下所示:

代码语言:javascript
复制
# Get the result row from the user.
result_row = self.compute(dates[i], assets, *inputs)
# Copy the user's result into our output buffer.
output[i] = result_row

如果这是API,那么我们至少要为每次调用用户的compute支付以下费用

  1. 分配用户将返回的~64000字节数组。
  2. 将用户计算的数据复制到用户的输出数组中。
  3. 从用户的输出数组复制到我们自己的更大的数组中。

利用现有的API,我们避免了成本(1)和(3)。

尽管如此,我们已经对CustomFactors的工作方式进行了更改,从而使上述一些优化变得不那么有用。特别是,我们现在只将数据传递给compute,以获取当天未被屏蔽的资产,这需要在调用compute之前和之后对输出数组进行部分复制。

尽管如此,还是有一些设计上的理由来选择现有的API。特别是,让引擎控制输出分配使我们更容易为多输出因素传递重新阵列

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/37405998

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档