提交 805f845d authored 作者: Olivier Breuleux's avatar Olivier Breuleux

added fallback in experimental_linker

上级 bc3f8854
...@@ -7,38 +7,76 @@ import core ...@@ -7,38 +7,76 @@ import core
import opt import opt
from copy import copy from copy import copy
def experimental_linker(env, target = None): def experimental_linker(env, target = None):
def fetch(op): order = env.toposort()
for op in order:
op.refresh()
py_ops = set()
thunks = []
for op in order:
try: try:
factory = op.c_thunk_factory() factory = op.c_thunk_factory()
# print "yea %s" % op for input in op.inputs:
producer = input.owner
if producer in py_ops:
result = lambda factory = factory: cutils.run_cthunk(factory())
break
else:
thunk = factory() thunk = factory()
return lambda: cutils.run_cthunk(thunk) result = lambda thunk = thunk: cutils.run_cthunk(thunk)
except NotImplementedError: except NotImplementedError:
# print "nope %s" % op result = op._perform
return op._perform py_ops.add(op)
order = env.toposort() thunks.append((result, op._perform_like_c))
for op in order:
op.refresh()
# for op in order:
# print op
# print 'ispecs: ', [input.spec for input in op.inputs]
# print 'ospecs: ', [output.spec for output in op.outputs]
thunks = [fetch(op) for op in order]
def ret(): def ret():
# print "==================================================" for thunk, fallback in thunks:
# for thunk, op in zip(thunks, order): try:
# print op
# print 'in: ', [id(input.data) for input in op.inputs]
# print 'out:', [id(output.data) for output in op.outputs]
# thunk()
for thunk in thunks:
thunk() thunk()
except NotImplementedError:
fallback()
if not target: if not target:
return ret return ret
else: else:
raise NotImplementedError("Cannot write thunk representation to a file.") raise NotImplementedError("Cannot write thunk representation to a file.")
# def experimental_linker(env, target = None):
# def fetch(op):
# try:
# factory = op.c_thunk_factory()
# # print "yea %s" % op
# thunk = factory()
# return lambda: cutils.run_cthunk(thunk)
# except NotImplementedError:
# # print "nope %s" % op
# return op._perform
# order = env.toposort()
# for op in order:
# op.refresh()
# # for op in order:
# # print op
# # print 'ispecs: ', [input.spec for input in op.inputs]
# # print 'ospecs: ', [output.spec for output in op.outputs]
# thunks = [fetch(op) for op in order]
# def ret():
# # print "=================================================="
# # for thunk, op in zip(thunks, order):
# # print op
# # print 'in: ', [id(input.data) for input in op.inputs]
# # print 'out:', [id(output.data) for output in op.outputs]
# # thunk()
# for thunk in thunks:
# thunk()
# if not target:
# return ret
# else:
# raise NotImplementedError("Cannot write thunk representation to a file.")
class profile_linker: class profile_linker:
def __init__(self, env): def __init__(self, env):
self.order = env.toposort() self.order = env.toposort()
......
...@@ -670,14 +670,14 @@ def tensor_scalar_impl(impl): ...@@ -670,14 +670,14 @@ def tensor_scalar_impl(impl):
return ret return ret
class tensor_scalar_op(elemwise): class tensor_scalar_op(elemwise):
def c_init((x, _a), (z, )):
return "_a_dtype a = ((_a_dtype*)PyArray_DATA(_a))[0];"
@classmethod @classmethod
def variable_names(cls): def variable_names(cls):
return (['x', '_a'], ['z', ]) return (['x', '_a'], ['z', ])
@classmethod @classmethod
def loop_variables(cls): def loop_variables(cls):
return (['x', ], ['z', ]) return (['x', ], ['z', ])
def c_init((x, _a), (z, )):
return "_a_dtype a = ((_a_dtype*)PyArray_DATA(_a))[0];"
def _c_foreach(self): def _c_foreach(self):
return "z_i = %s;" % self.c_expr return "z_i = %s;" % self.c_expr
...@@ -1053,47 +1053,55 @@ class transpose(omega_op, view): ...@@ -1053,47 +1053,55 @@ class transpose(omega_op, view):
return (numpy.ndarray, x[1], (x[2][1], x[2][0])) return (numpy.ndarray, x[1], (x[2][1], x[2][0]))
def c_impl((x, ), (xt, )): def c_impl((x, ), (xt, )):
return """ return """
const int l = x->nd;
if (xt->nd != x->nd)
{
// this technique comes from PyArray_Resize()
npy_intp * dimptr = (npy_intp*)PyDimMem_RENEW(xt->dimensions, 2 * x->nd);
if (!dimptr)
{
fprintf(stderr, "%i: %p\\n", __LINE__, dimptr);
assert(!"dammit");
}
xt->nd = x->nd;
xt->dimensions = dimptr;
xt->strides = dimptr + x->nd;
//fprintf(stderr, "transpose: %i %i %i %i\\n", x->dimensions[0], x->dimensions[1], x->strides[0], x->strides[1]);
for (int i = 0; i < x->dimensions[0]; i++) {
for (int j = 0; j < x->dimensions[1]; j++) {
*((xt_dtype*)PyArray_GETPTR2(xt, j, i)) = *((x_dtype*)PyArray_GETPTR2(x, i, j));
} }
//fprintf(stderr, "%s %i %p\\n", __FILE__, __LINE__, xt->base);
if ( xt->base != (PyObject*)x)
{
//fprintf(stderr, "%i: %p\\n", __LINE__, xt->base);
if ((xt->base) and (xt->base != Py_None)) Py_DECREF(xt->base);
Py_INCREF(x);
xt->base = (PyObject*)x;
} }
xt->data = x->data;
for (int i = 0; i < l; ++i)
{
xt->dimensions[i] = x->dimensions[l-i-1];
xt->strides[i] = x->strides[l-i-1];
//fprintf(stderr, "%li\t", x->dimensions[i]);
}
//fprintf(stderr, "\\n");
xt->flags &= ~NPY_OWNDATA;
PyArray_UpdateFlags(xt, NPY_CONTIGUOUS|NPY_FORTRAN|NPY_ALIGNED|NPY_WRITEABLE);
//this function is described in
// ~/zzz.NOBACKUP/pub/src/numpy-1.0.3.1/numpy/core/src/arrayobject.c:1890
return 0;
""" """
# return """
# const int l = x->nd;
# if (xt->nd != x->nd)
# {
# // this technique comes from PyArray_Resize()
# npy_intp * dimptr = (npy_intp*)PyDimMem_RENEW(xt->dimensions, 2 * x->nd);
# if (!dimptr)
# {
# fprintf(stderr, "%i: %p\\n", __LINE__, dimptr);
# assert(!"dammit");
# }
# xt->nd = x->nd;
# xt->dimensions = dimptr;
# xt->strides = dimptr + x->nd;
# //fprintf(stderr, "transpose: %i %i %i %i\\n", x->dimensions[0], x->dimensions[1], x->strides[0], x->strides[1]);
# }
# //fprintf(stderr, "%s %i %p\\n", __FILE__, __LINE__, xt->base);
# if ( xt->base != (PyObject*)x)
# {
# //fprintf(stderr, "%i: %p\\n", __LINE__, xt->base);
# if ((xt->base) and (xt->base != Py_None)) Py_DECREF(xt->base);
# Py_INCREF(x);
# xt->base = (PyObject*)x;
# }
# xt->data = x->data;
# for (int i = 0; i < l; ++i)
# {
# xt->dimensions[i] = x->dimensions[l-i-1];
# xt->strides[i] = x->strides[l-i-1];
# //fprintf(stderr, "%li\t", x->dimensions[i]);
# }
# //fprintf(stderr, "\\n");
# xt->flags &= ~NPY_OWNDATA;
# PyArray_UpdateFlags(xt, NPY_CONTIGUOUS|NPY_FORTRAN|NPY_ALIGNED|NPY_WRITEABLE);
# //this function is described in
# // ~/zzz.NOBACKUP/pub/src/numpy-1.0.3.1/numpy/core/src/arrayobject.c:1890
# return 0;
# """
def transpose_copy(x): def transpose_copy(x):
return array_copy(transpose(x)) return array_copy(transpose(x))
......
...@@ -229,6 +229,15 @@ class PythonOp(Op): ...@@ -229,6 +229,15 @@ class PythonOp(Op):
for result, output in zip(results, self.outputs): for result, output in zip(results, self.outputs):
output.set_value(result) output.set_value(result)
def _perform_like_c(self):
results = self._impl()
if self.nout == 1:
self.out.set_value(results)
else:
assert self.nout == len(results)
for result, output in zip(results, self.outputs):
output.data[:] = result
def compute(self): def compute(self):
for input in self.inputs: for input in self.inputs:
if input.data is UNCOMPUTED: if input.data is UNCOMPUTED:
......
...@@ -14,7 +14,6 @@ def optimizer(lst): ...@@ -14,7 +14,6 @@ def optimizer(lst):
begin = gof.SeqOptimizer([]) begin = gof.SeqOptimizer([])
end = gof.SeqOptimizer([gof.DummyRemover]) end = gof.SeqOptimizer([gof.DummyRemover])
seq_opt = gof.SeqOptimizer(begin + lst + end) seq_opt = gof.SeqOptimizer(begin + lst + end)
print 'seq_opt', seq_opt
return gof.PythonOpt(gof.MergeOptMerge(seq_opt)) return gof.PythonOpt(gof.MergeOptMerge(seq_opt))
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论