Package codepy ::
Module elementwise
|
|
1 """Elementwise functionality."""
2
3 from __future__ import division
4
5 __copyright__ = "Copyright (C) 2009 Andreas Kloeckner"
6
7
8
9
10 from pytools import memoize
11 import numpy
12 from codepy.cgen import POD, Value, dtype_to_ctype
21
23 return "%s(%r, %s)" % (
24 self.__class__.__name__,
25 self.name,
26 self.dtype)
27
30 return Value("numpy_array<%s >" % dtype_to_ctype(self.dtype),
31 self.name+"_ary")
32
34 return self.name + "_ary"
35
36 struct_char = "P"
37
41
44
45 @property
47 return self.dtype.char
48
53 from codepy.bpl import BoostPythonModule
54
55 from codepy.cgen import FunctionBody, FunctionDeclaration, \
56 Value, POD, Struct, For, Initializer, Include, Statement, \
57 Line, Block
58
59 S = Statement
60
61 mod = BoostPythonModule()
62 mod.add_to_preamble([
63 Include("pyublas/numpy.hpp"),
64 ])
65
66 mod.add_to_module([
67 S("namespace ublas = boost::numeric::ublas"),
68 S("using namespace pyublas"),
69 Line(),
70 ])
71
72 body = Block([
73 Initializer(
74 Value("numpy_array<%s >::iterator"
75 % dtype_to_ctype(varg.dtype),
76 varg.name),
77 "args.%s_ary.begin()" % varg.name)
78 for varg in arguments if isinstance(varg, VectorArg)]
79 +[Initializer(
80 sarg.declarator(), "args." + sarg.name)
81 for sarg in arguments if isinstance(sarg, ScalarArg)]
82 )
83
84 body.extend([
85 Line(),
86 For("unsigned i = 0",
87 "i < codepy_length",
88 "++i",
89 Block([S(operation)])
90 )
91 ])
92
93 arg_struct = Struct("arg_struct",
94 [arg.declarator() for arg in arguments])
95 mod.add_struct(arg_struct, "ArgStruct")
96 mod.add_to_module([Line()])
97
98 mod.add_function(
99 FunctionBody(
100 FunctionDeclaration(
101 Value("void", name),
102 [POD(numpy.uintp, "codepy_length"),
103 Value("arg_struct", "args")]),
104 body))
105
106 return mod
107
124
125
126
127
128 -def get_elwise_kernel(arguments, operation, name="kernel", toolchain=None,
129 wait_on_error=False):
130 return getattr(get_elwise_module_binary(
131 arguments, operation, name, toolchain, wait_on_error), name)
132
137 - def __init__(self, arguments, operation, name="kernel", toolchain=None,
138 wait_on_error=False):
139 self.arguments = arguments
140 self.module = get_elwise_module_binary(
141 arguments, operation, name, toolchain, wait_on_error)
142 self.func = getattr(self.module, name)
143
144 self.vec_arg_indices = [i for i, arg in enumerate(arguments)
145 if isinstance(arg, VectorArg)]
146
147 assert self.vec_arg_indices, \
148 "ElementwiseKernel can only be used with functions that have at least one " \
149 "vector argument"
150
152 vectors = []
153
154 from pytools import single_valued
155 size = single_valued(args[i].size for i in self.vec_arg_indices)
156
157
158 arg_struct = self.module.ArgStruct()
159 for arg_descr, arg in zip(self.arguments, args):
160 setattr(arg_struct, arg_descr.arg_name(), arg)
161
162 assert not arg_struct.__dict__
163
164 self.func(size, arg_struct)
165
172 comp_count = len(vector_dtypes)
173 from pytools import flatten
174 return ElementwiseKernel([VectorArg(result_dtype, "result")] + list(flatten(
175 (ScalarArg(scalar_dtypes[i], "a%d_fac" % i),
176 VectorArg(vector_dtypes[i], "a%d" % i))
177 for i in range(comp_count))),
178 "result[i] = " + " + ".join("a%d_fac*a%d[i]" % (i, i)
179 for i in range(comp_count)))
180
186 from pytools import common_dtype
187 result_dtype = common_dtype(scalar_dtypes+vector_dtypes)
188
189 return make_linear_comb_kernel_with_result_dtype(
190 result_dtype, scalar_dtypes, vector_dtypes), result_dtype
191
192
193
194
195
196 if __name__ == "__main__":
197 import pyublas
198
199 a = numpy.random.rand(50000)
200 b = numpy.random.rand(50000)
201
202 dtype = a.dtype
203
204 lin_comb = ElementwiseKernel([
205 ScalarArg(dtype, "a_fac"), VectorArg(dtype, "a"),
206 ScalarArg(dtype, "b_fac"), VectorArg(dtype, "b"),
207 VectorArg(dtype, "c"),
208 ],
209 "c[i] = a_fac*a[i] + b_fac*b[i]")
210
211 c = numpy.empty_like(a)
212 lin_comb(5, a, 6, b, c)
213
214 import numpy.linalg as la
215 print la.norm(c - (5*a+6*b))
216