Skip to content

Commit

Permalink
Add some more tests
Browse files Browse the repository at this point in the history
  • Loading branch information
markflorisson committed Sep 16, 2012
1 parent caaf3e6 commit 042927d
Show file tree
Hide file tree
Showing 8 changed files with 64 additions and 41 deletions.
20 changes: 14 additions & 6 deletions miniast.py
Expand Up @@ -111,6 +111,9 @@ class Context(object):
use_llvm = False
optimize_broadcasting = True

shape_type = minitypes.Py_ssize_t.pointer()
strides_type = shape_type

astbuilder_cls = None
codegen_cls = UndocClassAttribute(codegen.VectorCodegen)
cleanup_codegen_cls = UndocClassAttribute(codegen.CodeGenCleanup)
Expand Down Expand Up @@ -186,8 +189,15 @@ def run(self, ast, specializer_classes, graphviz_outfile=None,
def debug_c(self, ast, specializer, astbuilder_cls=None):
"Generate C code (for debugging)"
context = CContext()

if astbuilder_cls:
context.astbuilder_cls = astbuilder_cls
else:
context.astbuilder_cls = self.astbuilder_cls

context.shape_type = self.shape_type
context.strides_type = self.strides_type

context.debug = self.debug
result = context.run(ast, [specializer]).next()
_, specialized_ast, _, (proto, impl) = result
Expand Down Expand Up @@ -313,9 +323,6 @@ class ASTBuilder(object):
and which makes it convenient to build up complex ASTs concisely.
"""

shape_type = minitypes.Py_ssize_t.pointer()
strides_type = shape_type

# the 'pos' attribute is set for each visit to each node by
# the ASTMapper
pos = None
Expand Down Expand Up @@ -372,7 +379,7 @@ def function(self, name, body, args, shapevar=None, posinfo=None,
arguments to the function ``(filename, lineno, column)``.
"""
if shapevar is None:
shapevar = self.variable(minitypes.Py_ssize_t.pointer(), 'shape')
shapevar = self.variable(self.context.shape_type, 'shape')

arguments, scalar_arguments = [], []
for arg in args:
Expand Down Expand Up @@ -748,7 +755,7 @@ def extent(self, variable, index, function):

def stridesvar(self, variable):
"Return the strides variable for the given array operand"
return StridePointer(self.pos, minitypes.Py_ssize_t.pointer(), variable)
return StridePointer(self.pos, self.context.strides_type, variable)

def stride(self, variable, index):
"Return the stride of array operand `variable` at integer `index`"
Expand Down Expand Up @@ -886,7 +893,8 @@ def _create_data_pointer(self, function, argument, i):
def stridesvar(self, variable):
"Return the strides variable for the given array operand"
if not hasattr(variable, 'strides_pointer'):
temp = self.temp(self.strides_type, variable.name + "_stride_temp")
temp = self.temp(self.context.strides_type,
variable.name + "_stride_temp")
variable.strides_pointer = temp

return variable.strides_pointer
Expand Down
11 changes: 5 additions & 6 deletions miniutils.py
Expand Up @@ -14,11 +14,6 @@
### Convenience utilities
#

def build_function(context, variables, expr, name=None):
"Build a minivect function"
b = context.astbuilder
body = b.nditerate(expr)
return b.build_function(variables, body, name)

def specialize(context, specializer_cls, ast, print_tree=False):
"Specialize an AST with given specializer and compile"
Expand All @@ -41,7 +36,7 @@ def __init__(self, context, specializer, variables, expr, name=None):
self.context = context
self.specializer = specializer
self.variables = variables
self.minifunc = build_function(context, variables, expr, name)
self.minifunc = self.b.build_function(variables, expr, name)
self.specialized_ast, (self.lfunc, self.ctypes_func) = specialize(
context, specializer, self.minifunc)

Expand Down Expand Up @@ -69,6 +64,10 @@ def get_ctypes_func_and_args(self, arrays):
def __call__(self, *args, **kwargs):
import numpy as np

# print self.minifunc.ndim
# self.minifunc.print_tree(self.context)
print self.context.debug_c(self.minifunc, self.specializer)

out = kwargs.pop('out', None)
assert not kwargs, kwargs

Expand Down
2 changes: 1 addition & 1 deletion pytest.ini
@@ -1,2 +1,2 @@
[pytest]
addopts = --doctest-modules --ignore=bench
addopts = --doctest-modules --ignore=bench --tb=short
7 changes: 5 additions & 2 deletions specializers.py
Expand Up @@ -1062,7 +1062,7 @@ class StridedCInnerContigSpecializer(OrderedSpecializer):
on the 'order' attribute).
"""

specialization_name = "inner_contig_c"
specialization_name = "inner_contig"
order = "C"

is_inner_contig_specializer = True
Expand Down Expand Up @@ -1111,6 +1111,8 @@ def visit_NDIterate(self, node):
"""
b = self.astbuilder

assert not list(self.treepath(node, '//NDIterate'))

original_expr = specialize_ast(node.body)

# start by generating a C or Fortran ordered loop
Expand Down Expand Up @@ -1352,7 +1354,7 @@ class CTiledStridedSpecializer(StridedSpecializer):
The blocksize may be overridden through the get_blocksize method, in
a specializer subclass or mixin (see miniast.Context.specializer_mixin_cls).
"""
specialization_name = "tiled_c"
specialization_name = "tiled"
order = "C"
is_tiled_specializer = True

Expand All @@ -1373,6 +1375,7 @@ def untiled_order(self):
return self.function.ndim - 1 - 2, -1, -1

def visit_NDIterate(self, node):
assert self.function.ndim >= 2
return self._tile_in_two_dimensions(node)

def _tile_in_two_dimensions(self, node):
Expand Down
7 changes: 3 additions & 4 deletions tests/llvm_testutils.py
Expand Up @@ -6,6 +6,9 @@
llvm_context = context = get_llvm_context()
b = context.astbuilder

#context.debug = True
# context.debug_elements = True

def get_array(shape=(130, 160), dtype=np.float32, order='C'):
return np.arange(np.prod(shape), dtype=dtype).reshape(shape, order=order)

Expand All @@ -14,10 +17,6 @@ def specialize(specializer_cls, ast, context=None, print_tree=False):
context=context or llvm_context,
print_tree=print_tree)

def invoke(specializer_name, minifunc, *args):
sp = sps[specializer_name]
_, (ctypes_func, lfunc) = specialize(sp, minifunc)

class MiniFunction(miniutils.MiniFunction):
def __init__(self, sp_name, variables, expr, name=None, context=None):
context = context or llvm_context
Expand Down
2 changes: 1 addition & 1 deletion tests/test_hoisting.py
Expand Up @@ -9,7 +9,7 @@

import pytest

cinner = sps['inner_contig_c']
cinner = sps['inner_contig']

@pytest.mark.skipif('not xmldumper.have_lxml')
def test_hoist():
Expand Down
51 changes: 31 additions & 20 deletions tests/test_specializations.py
Expand Up @@ -7,31 +7,42 @@ def build_expr(type):
expr = b.assign(out, b.add(v1, b.mul(v2, v3)))
return vars, expr

def build_kernels(specialization_name, **kw):
funcs = []
for ndim in range(1, 4):
vars, expr = build_expr(minitypes.ArrayType(float_, ndim, **kw))
funcs.append(MiniFunction(specialization_name, vars, expr))
def build_kernel(specialization_name, ndim, **kw):
vars, expr = build_expr(minitypes.ArrayType(float_, ndim, **kw))
func = MiniFunction(specialization_name, vars, expr)
return func

return funcs
def build_kernels(specialization_name, min_ndim=1, max_ndim=3, **kw):
return [build_kernel(specialization_name, ndim)
for ndim in range(min_ndim, max_ndim + 1)]

arrays2d = [get_array(), get_array(), get_array()]
arrays1d = [a[0] for a in arrays2d]
arrays3d = [a[:, None, :] for a in arrays2d]
arrays = [(arrays1d, arrays2d, arrays3d)]

@pytest.mark.parametrize(("arrays", "specializer_names"),
[(arrays, ['contig'])])
def test_specializations(arrays, specializer_names):
"""
>>> test_specializations(arrays, ['contig'])
contig
"""
for name in specializer_names:
print name
f1d, f2d, f3d = build_kernels(name)
for (x1, y1, z1), (x2, y2, z2), (x3, y3, z3) in arrays:
assert np.all(f1d(x1, y1, z1) == x1 + y1 * z1)
assert np.all(f2d(x2, y2, z2) == x2 + y2 * z2)
assert np.all(f3d(x3, y3, z3) == x3 + y3 * z3)
def pytest_generate_tests(metafunc):
if metafunc.function is test_specializations:
specializations = [s for s in sps.keys()
if not s.endswith(('_sse', '_avx'))]
metafunc.parametrize("arrays", arrays)
metafunc.parametrize("specialization_name", specializations)
metafunc.parametrize("ndim", range(1, 4))


def test_specializations(arrays, specialization_name, ndim):
if 'tiled' in specialization_name and ndim < 2:
return

if 'fortran' in specialization_name:
arrays = [(x.T, y.T, z.T) for x, y, z in arrays]

func = build_kernel(specialization_name, ndim)
x, y, z = arrays[ndim - 1]

print x.strides, y.strides, z.strides
assert np.all(func(x, y, z) == x + y * z)

specializations = [s for s in sps.keys()
if not s.endswith(('_sse', '_avx'))]
print specializations
5 changes: 4 additions & 1 deletion tests/testutils.py
Expand Up @@ -21,7 +21,10 @@ def getcontext():
return miniast.CContext()

def get_llvm_context():
return miniast.LLVMContext()
context = miniast.LLVMContext()
context.shape_type = minitypes.npy_intp.pointer()
context.strides_type = context.shape_type
return context

def build_vars(*types):
return [b.variable(type, 'op%d' % i) for i, type in enumerate(types)]
Expand Down

0 comments on commit 042927d

Please sign in to comment.