我是在MXNet中编写C自定义运算符,并且在查找运算符调用时 kAddTo
时的文档时遇到问题 . 作为一个最小的例子,假设我的新运算符被称为 foo()
,我想执行以下计算:
A = mx.sym.Variable('A')
B = mx.sym.Variable('B')
T = mx.sym.foo(A)
T += mx.sym.foo(B)
通常,如何确保上面的第四行累积到T而不是为 mx.sym.foo(B)
的结果创建新的临时存储,然后执行 T = T + temp
计算?
(使用Kernighan-Ritchie调试器,也就是打印语句,我发现 kWriteTo
在第3行和第4行都设置了 . 枚举 kAddTo
永远不会被设置 . )
关于我的具体问题的更多细节:在我当前的实现中 foo()
在执行计算之前将输出内存清零,并使用适当的值填充它 . 我绝对只想在创建新输出位置时执行此归零,而不是在累积到现有输出位置时执行此归零 .
Update
离线,一位同事建议使用
mx.sym.elemwise_add(lhs=T, rhs=mx.sym.foo(B), out=T)
代替上面第4行 . 但是,我仍然看到 kWriteTo
正在两个计算行中设置 . 然后我收到了以下回复:
“内存规划和就地操作是自动的 . 它将自动完成 . 用户无需担心它 . “,这可能意味着req [0]在这种情况下不是一个准确的指标 . 如果要验证它是否为就地addTo,可以打印输出[0] .dptr_和lhs.dptr_的值以查看它们是否相等 .
我还没检查过这个 .
1 回答
操作员无法控制将在哪种模式下执行 . 问题是,只有图优化器知道使用运算符的上下文,并且如果运算符需要在
kWriteTo
或kAddTo
中执行,则可以做出决定 . 更确切地说,这发生了_137408_ . 即使在某些情况下它已在kAddTo
中执行,由于优化计算图形的逻辑发生变化,将来可能会改变此行为 .这意味着操作员无法控制执行的模式,但操作员必须严格遵守已请求的模式(
kWriteTo
或kAddTo
) . 例如,如果模式是kWriteTo
并且操作员尝试将diff添加到输出,而不是覆盖其中的内容,则会导致不可预测的结果,因为输出可能会填充垃圾 . 另一方面,如果模式是kAddTo
但操作员不支持它可能会更糟,因为,不是将结果添加到输出,它将覆盖输出(这样的情况通常很难调试) . 这会不时地导致像this one这样的错误 .简而言之:
你不能,这不是运营商决定执行哪种模式 . 即使配置使用模式
kAddTo
与未来版本的MXNet . 同样在将来,可能会创建新的API以向图形优化器(或建议)发送提示以使用特定模式 . 但我不知道这种发展 .现在的问题是:“MXNet 0.10 / 0.11在哪种特殊情况下会使用
kAddTo
”?通过查看following code,这很棘手:
看起来
kAddTo
只在_grad_add
期间使用,这很难过 . 这也许是一个错误,因为可能代替:实际意图是: