Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
P
pytensor
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
testgroup
pytensor
Commits
f16cd012
提交
f16cd012
authored
5月 03, 2012
作者:
Arnaud Bergeron
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Cleanup of the error handling in lazy_rec_eval().
上级
ac42ce74
显示空白字符变更
内嵌
并排
正在显示
1 个修改的文件
包含
71 行增加
和
83 行删除
+71
-83
lazylinker_c.c.txt
theano/gof/lazylinker_c.c.txt
+71
-83
没有找到文件。
theano/gof/lazylinker_c.c.txt
浏览文件 @
f16cd012
...
@@ -291,27 +291,17 @@ CLazyLinker_init(CLazyLinker *self, PyObject *args, PyObject *kwds)
...
@@ -291,27 +291,17 @@ CLazyLinker_init(CLazyLinker *self, PyObject *args, PyObject *kwds)
// allocated and initialize thunk_cptr_data and thunk_cptr_fn
// allocated and initialize thunk_cptr_data and thunk_cptr_fn
if (n_applies)
if (n_applies)
{
{
self->thunk_cptr_data = (void**)
malloc(n_applies *
sizeof(void*));
self->thunk_cptr_data = (void**)
calloc(n_applies,
sizeof(void*));
self->thunk_cptr_fn = (void**)
malloc(n_applies *
sizeof(void*));
self->thunk_cptr_fn = (void**)
calloc(n_applies,
sizeof(void*));
self->is_lazy = (int*)
malloc(n_applies *
sizeof(int));
self->is_lazy = (int*)
calloc(n_applies,
sizeof(int));
self->node_prereqs = (Py_ssize_t**)
malloc(n_applies*
sizeof(Py_ssize_t*));
self->node_prereqs = (Py_ssize_t**)
calloc(n_applies,
sizeof(Py_ssize_t*));
self->node_n_prereqs = (Py_ssize_t*)
malloc(n_applies*
sizeof(Py_ssize_t));
self->node_n_prereqs = (Py_ssize_t*)
calloc(n_applies,
sizeof(Py_ssize_t));
assert(self->node_prereqs);
assert(self->node_prereqs);
assert(self->node_n_prereqs);
assert(self->node_n_prereqs);
assert(self->is_lazy);
assert(self->is_lazy);
assert(self->thunk_cptr_fn);
assert(self->thunk_cptr_fn);
assert(self->thunk_cptr_data);
assert(self->thunk_cptr_data);
// init these basic arrays
for (int i = 0; i < n_applies; ++i)
{
self->thunk_cptr_data[i] = NULL;
self->thunk_cptr_fn[i] = NULL;
self->is_lazy[i] = 1;
self->node_prereqs[i] = NULL;
self->node_n_prereqs[i] = 0;
}
for (int i = 0; i < n_applies; ++i)
for (int i = 0; i < n_applies; ++i)
{
{
PyObject * thunk = PyList_GetItem(self->thunks, i);
PyObject * thunk = PyList_GetItem(self->thunks, i);
...
@@ -326,11 +316,6 @@ CLazyLinker_init(CLazyLinker *self, PyObject *args, PyObject *kwds)
...
@@ -326,11 +316,6 @@ CLazyLinker_init(CLazyLinker *self, PyObject *args, PyObject *kwds)
Py_DECREF(cthunk);
Py_DECREF(cthunk);
// cthunk is kept alive by membership in self->thunks
// cthunk is kept alive by membership in self->thunks
}
}
else
{
self->thunk_cptr_fn[i] = NULL;
self->thunk_cptr_data[i] = NULL;
}
PyObject * el_i = PyList_GetItem(is_lazy, i);
PyObject * el_i = PyList_GetItem(is_lazy, i);
self->is_lazy[i] = PyNumber_AsSsize_t(el_i, NULL);
self->is_lazy[i] = PyNumber_AsSsize_t(el_i, NULL);
...
@@ -537,18 +522,19 @@ static int c_call(CLazyLinker * self, Py_ssize_t node_idx, int verbose)
...
@@ -537,18 +522,19 @@ static int c_call(CLazyLinker * self, Py_ssize_t node_idx, int verbose)
static
static
int lazy_rec_eval(CLazyLinker * self, Py_ssize_t var_idx, PyObject*one, PyObject*zero)
int lazy_rec_eval(CLazyLinker * self, Py_ssize_t var_idx, PyObject*one, PyObject*zero)
{
{
PyObject *rval = NULL;
int verbose = 0;
int verbose = 0;
if (verbose) fprintf(stderr, "lazy_rec computing %i\n", (int)var_idx);
int err = 0;
int err = 0;
if (verbose) fprintf(stderr, "lazy_rec computing %i\n", (int)var_idx);
if (self->var_computed[var_idx] || !self->var_has_owner[var_idx])
if (self->var_computed[var_idx] || !self->var_has_owner[var_idx])
{
return 0;
return 0;
}
else
{
Py_ssize_t owner_idx = self->var_owner[var_idx];
Py_ssize_t owner_idx = self->var_owner[var_idx];
// STEP 1: compute the pre-requirements of the node
// STEP 1: compute the pre-requirements of the node
// Includes input nodes for non-lazy ops.
for (int i = 0; i < self->node_n_prereqs[owner_idx]; ++i)
for (int i = 0; i < self->node_n_prereqs[owner_idx]; ++i)
{
{
Py_ssize_t prereq_idx = self->node_prereqs[owner_idx][i];
Py_ssize_t prereq_idx = self->node_prereqs[owner_idx][i];
...
@@ -564,7 +550,7 @@ int lazy_rec_eval(CLazyLinker * self, Py_ssize_t var_idx, PyObject*one, PyObject
...
@@ -564,7 +550,7 @@ int lazy_rec_eval(CLazyLinker * self, Py_ssize_t var_idx, PyObject*one, PyObject
if (self->is_lazy[owner_idx])
if (self->is_lazy[owner_idx])
{
{
// update the compute_map cells corresponding to the inputs of this thunk
// update the compute_map cells corresponding to the inputs of this thunk
for (int i = 0; i < self->node_n_inputs[owner_idx] && (!err)
; ++i)
for (int i = 0; i < self->node_n_inputs[owner_idx]
; ++i)
{
{
int in_idx = self->node_inputs[owner_idx][i];
int in_idx = self->node_inputs[owner_idx][i];
if (self->var_computed[in_idx])
if (self->var_computed[in_idx])
...
@@ -577,19 +563,20 @@ int lazy_rec_eval(CLazyLinker * self, Py_ssize_t var_idx, PyObject*one, PyObject
...
@@ -577,19 +563,20 @@ int lazy_rec_eval(CLazyLinker * self, Py_ssize_t var_idx, PyObject*one, PyObject
Py_INCREF(zero);
Py_INCREF(zero);
err = PyList_SetItem(self->var_computed_cells[in_idx], 0, zero);
err = PyList_SetItem(self->var_computed_cells[in_idx], 0, zero);
}
}
}
if (err) goto fail;
if (err)
{
set_position_of_error(self, owner_idx);
return err;
}
}
PyObject *
rval = pycall(self, owner_idx, verbose);
rval = pycall(self, owner_idx, verbose);
// refcounting - rval is new ref
// refcounting - rval is new ref
//TODO: to prevent infinite loops
//TODO: to prevent infinite loops
// - consider check that a thunk does not ask for an input that is already computed
// - consider check that a thunk does not ask for an input that is already computed
if (rval) //call returned normally (no exception
)
if (rval == NULL
)
{
{
assert (PyErr_Occurred());
err = 1;
goto fail;
}
//update the computed-ness of any output cells
//update the computed-ness of any output cells
for (int i = 0; i < self->node_n_outputs[owner_idx]; ++i)
for (int i = 0; i < self->node_n_outputs[owner_idx]; ++i)
{
{
...
@@ -598,68 +585,65 @@ int lazy_rec_eval(CLazyLinker * self, Py_ssize_t var_idx, PyObject*one, PyObject
...
@@ -598,68 +585,65 @@ int lazy_rec_eval(CLazyLinker * self, Py_ssize_t var_idx, PyObject*one, PyObject
Py_ssize_t N = PyNumber_AsSsize_t(el_i, PyExc_IndexError);
Py_ssize_t N = PyNumber_AsSsize_t(el_i, PyExc_IndexError);
if (PyErr_Occurred())
if (PyErr_Occurred())
{
{
Py_DECREF(rval);
err = -1;
set_position_of_error(self, owner_idx);
goto pyfail;
return -1;
}
}
assert (N==0 || N==1);
assert (N==0 || N==1);
self->var_computed[out_idx] = N;
self->var_computed[out_idx] = N;
}
}
if (!self->var_computed[var_idx])
if (!self->var_computed[var_idx])
{
{
if (PyList_Check(rval))
/*
* If self is not computed after the call, this means that some
* inputs are needed. Compute the ones on the returned list
* and try to compute the current node again (with recursive call).
* This allows a node to request more nodes more than once before
* finally yielding a result.
*/
if (!PyList_Check(rval))
{
{
if (PyList_Size(rval))
//TODO: More helpful error to help find *which node* made this
// bad thunk
PyErr_SetString(PyExc_TypeError,
"lazy thunk should return a list");
err = 1;
goto pyfail;
}
if (!PyList_Size(rval))
{
{
for (int i = 0; i < PyList_Size(rval) && (!err); ++i)
PyErr_SetString(PyExc_ValueError,
"lazy thunk returned empty list without computing output");
err = 1;
goto pyfail;
}
for (int i = 0; i < PyList_Size(rval); ++i)
{
{
PyObject * el_i = PyList_GetItem(rval, i);
PyObject * el_i = PyList_GetItem(rval, i);
Py_ssize_t N = PyNumber_AsSsize_t(el_i, PyExc_IndexError);
Py_ssize_t N = PyNumber_AsSsize_t(el_i, PyExc_IndexError);
if (PyErr_Occurred())
if (PyErr_Occurred())
{
{
err = 1;
err = 1;
goto pyfail;
}
}
else
{
assert (N <= self->node_n_inputs[owner_idx]);
assert (N <= self->node_n_inputs[owner_idx]);
Py_ssize_t input_idx = self->node_inputs[owner_idx][N];
Py_ssize_t input_idx = self->node_inputs[owner_idx][N];
err = lazy_rec_eval(self, input_idx, one, zero);
err = lazy_rec_eval(self, input_idx, one, zero);
if (err) goto pyfail;
}
}
}
if (!err)
err = lazy_rec_eval(self, var_idx, one, zero);
}
else
{
PyErr_SetString(PyExc_ValueError,
"lazy thunk returned empty list without computing output");
err = 1;
set_position_of_error(self, owner_idx);
}
Py_DECREF(rval);
set_position_of_error(self, owner_idx);
return err;
}
else // don't know what it returned, but it wasn't right.
{
//TODO: More helpful error to help find *which node* made this
// bad thunk
PyErr_SetString(PyExc_TypeError,
"lazy thunk should list");
Py_DECREF(rval);
Py_DECREF(rval);
set_position_of_error(self, owner_idx);
/*
return 1;
* We intentionally skip all the end-of-function processing
}
* (mark outputs, GC) as it will be performed by the call
* that actually manages to compute the result.
*/
return lazy_rec_eval(self, var_idx, one, zero);
}
}
Py_DECREF(rval);
Py_DECREF(rval);
}
}
else // pycall returned NULL (internal error)
{
assert (PyErr_Occurred());
set_position_of_error(self, owner_idx);
return 1;
}
}
else //owner is not a lazy op. Ensure all intputs are evaluated.
else //owner is not a lazy op. Ensure all intputs are evaluated.
{
{
// loop over inputs to owner
// loop over inputs to owner
...
@@ -680,10 +664,11 @@ int lazy_rec_eval(CLazyLinker * self, Py_ssize_t var_idx, PyObject*one, PyObject
...
@@ -680,10 +664,11 @@ int lazy_rec_eval(CLazyLinker * self, Py_ssize_t var_idx, PyObject*one, PyObject
if (self->thunk_cptr_fn[owner_idx])
if (self->thunk_cptr_fn[owner_idx])
{
{
err = c_call(self, owner_idx, verbose);
err = c_call(self, owner_idx, verbose);
if (err) goto fail;
}
}
else
else
{
{
PyObject *
rval = pycall(self, owner_idx, verbose);
rval = pycall(self, owner_idx, verbose);
//rval is new ref
//rval is new ref
if (rval) //pycall returned normally (no exception)
if (rval) //pycall returned normally (no exception)
{
{
...
@@ -695,33 +680,36 @@ int lazy_rec_eval(CLazyLinker * self, Py_ssize_t var_idx, PyObject*one, PyObject
...
@@ -695,33 +680,36 @@ int lazy_rec_eval(CLazyLinker * self, Py_ssize_t var_idx, PyObject*one, PyObject
{
{
PyErr_SetString(PyExc_TypeError,
PyErr_SetString(PyExc_TypeError,
"non-lazy thunk should return None, not list");
"non-lazy thunk should return None, not list");
err=1;
err = 1;
set_position_of_error(self, owner_idx);
goto pyfail;
Py_DECREF(rval);
}
}
else // don't know what it returned, but it wasn't right.
else // don't know what it returned, but it wasn't right.
{
{
PyErr_SetObject(PyExc_TypeError, rval);
PyErr_SetObject(PyExc_TypeError, rval);
err=1;
err = 1;
set_position_of_error(self, owner_idx);
// We don't release rval since we put it in the error above
goto fail;
}
}
}
}
else // pycall returned NULL (internal error)
else // pycall returned NULL (internal error)
{
{
err=
1;
err =
1;
set_position_of_error(self, owner_idx)
;
goto fail
;
}
}
}
}
}
}
// loop over all outputs and mark them as computed
// loop over all outputs and mark them as computed
for (int i = 0; i < self->node_n_outputs[owner_idx] && (!err)
; ++i)
for (int i = 0; i < self->node_n_outputs[owner_idx]
; ++i)
{
{
self->var_computed[self->node_outputs[owner_idx][i]] = 1;
self->var_computed[self->node_outputs[owner_idx][i]] = 1;
}
}
}
return 0;
pyfail:
Py_DECREF(rval);
fail:
set_position_of_error(self, owner_idx);
return err;
return err;
}
}
PyObject *
PyObject *
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论