Permalink
Browse files

Specialize for contiguous operands

  • Loading branch information...
1 parent 6244394 commit 9b0fc9efd6252f1b670b9b14021c26594bcfa854 @markflorisson committed May 28, 2012
Showing with 75 additions and 11 deletions.
  1. +1 −0 Cython/Compiler/PyrexTypes.py
  2. +29 −11 Cython/Compiler/Vector.py
  3. +45 −0 tests/run/elementwise.pyx
@@ -476,6 +476,7 @@ def __init__(self, base_dtype, axes):
self.flags = MemoryView.get_buf_flags(self.axes)
self.is_c_contig, self.is_f_contig = MemoryView.is_cf_contig(self.axes)
+ self.is_contig = self.is_c_contig or self.is_f_contig
assert not (self.is_c_contig and self.is_f_contig)
self.mode = MemoryView.get_mode(axes)
View
@@ -3,9 +3,12 @@
from Cython.minivect import miniast
from Cython.minivect import minitypes
+from Cython.minivect import miniutils
from Cython.minivect import minierror
from Cython.minivect import specializers
+debug = False
+
class Context(miniast.CContext):
def getpos(self, node):
return node.pos
@@ -40,6 +43,8 @@ class ElementalNode(ExprNodes.ExprNode):
context: Context attribute
operands: all participating array views
function: miniast function wrapping the array expression
+
+ all_contig: whether all operands are contiguous
"""
subexprs = ['operands']
@@ -49,25 +54,31 @@ def result(self):
def generate_result_code(self, code):
function = self.function
- strided_specializer = specializers.StridedSpecializer(
- self.context, 'strided_specializer')
- codes = self.context.run(function, [strided_specializer])
+
+ if self.all_contig:
+ specializer = specializers.ContigSpecializer(self.context)
+ else:
+ specializer = specializers.StridedSpecializer(self.context)
+
+ codes = self.context.run(function, [specializer])
(specialized_function, codewriter, (proto, impl)), = codes
utility = Code.UtilityCode(proto=proto, impl=impl)
code.globalstate.use_utility_code(utility)
- # marker = '-' * 20
- # print marker, 'proto', marker
- # print proto
- # print marker, 'impl', marker
- # print impl
+
+ if debug:
+ marker = '-' * 20
+ print marker, 'proto', marker
+ print proto
+ print marker, 'impl', marker
+ print impl
array_type = PyrexTypes.c_array_type(PyrexTypes.c_py_ssize_t_type,
function.ndim)
shape = code.funcstate.allocate_temp(array_type, manage_ref=False)
for i in range(function.ndim):
code.putln("%s[%d] = 0;" % (shape, i))
- args = ["&%s" % shape]
+ args = ["&%s[0]" % shape]
for operand in self.operands:
result = operand.result()
if operand.type.is_memoryviewslice:
@@ -76,7 +87,10 @@ def generate_result_code(self, code):
code.putln( "%s[%d] = %s.shape[%d];" % (shape, i, result, i))
code.putln("}")
- args.extend(['%s.data' % result, "&%s.strides" % result])
+ tp = operand.type.dtype.declaration_code("")
+ args.append('(%s *) %s.data' % (tp, result))
+ if not self.all_contig:
+ args.append("&%s.strides[0]" % result)
else:
args.append(result)
@@ -150,8 +164,12 @@ def visit_elemental(self, node):
name = '__pyx_array_expression%d' % self.funccount
self.funccount += 1
function = b.function(name, body, astmapper.funcargs, shapevar)
+
+ all_contig = miniutils.all(op.type.is_contig
+ for op in astmapper.operands)
node = ElementalNode(node.pos, operands=astmapper.operands,
- function=function, context=self.minicontext)
+ function=function, context=self.minicontext,
+ all_contig=all_contig)
node = Nodes.ExprStatNode(node.pos, expr=node)
return node
View
@@ -11,3 +11,48 @@ def test_simple_binop_assign(int[:] m):
"""
m[:] = m * m
return m
+
+def test_simple_binop_assign_contig(int[::1] m):
+ """
+ >>> a = np.arange(10, dtype='i')
+ >>> np.asarray(test_simple_binop_assign_contig(a))
+ array([ 0, 1, 4, 9, 16, 25, 36, 49, 64, 81], dtype=int32)
+ """
+ m[:] = m * m
+ return m
+
+def test_simple_binop_assign_2d(int[:, :] m):
+ """
+ >>> a2d = np.arange(100, dtype='i').reshape(10, 10)
+ >>> np.asarray(test_simple_binop_assign_2d(a2d))
+ array([[ 0, 3, 6, 9, 12, 15, 18, 21, 24, 27],
+ [ 30, 33, 36, 39, 42, 45, 48, 51, 54, 57],
+ [ 60, 63, 66, 69, 72, 75, 78, 81, 84, 87],
+ [ 90, 93, 96, 99, 102, 105, 108, 111, 114, 117],
+ [120, 123, 126, 129, 132, 135, 138, 141, 144, 147],
+ [150, 153, 156, 159, 162, 165, 168, 171, 174, 177],
+ [180, 183, 186, 189, 192, 195, 198, 201, 204, 207],
+ [210, 213, 216, 219, 222, 225, 228, 231, 234, 237],
+ [240, 243, 246, 249, 252, 255, 258, 261, 264, 267],
+ [270, 273, 276, 279, 282, 285, 288, 291, 294, 297]], dtype=int32)
+ """
+ m[:] = m + m + m
+ return m
+
+def test_simple_binop_assign_contig_2d(int[:, :] m):
+ """
+ >>> a2d = np.arange(100, dtype='i').reshape(10, 10)
+ >>> np.asarray(test_simple_binop_assign_contig_2d(a2d))
+ array([[ 0, 3, 6, 9, 12, 15, 18, 21, 24, 27],
+ [ 30, 33, 36, 39, 42, 45, 48, 51, 54, 57],
+ [ 60, 63, 66, 69, 72, 75, 78, 81, 84, 87],
+ [ 90, 93, 96, 99, 102, 105, 108, 111, 114, 117],
+ [120, 123, 126, 129, 132, 135, 138, 141, 144, 147],
+ [150, 153, 156, 159, 162, 165, 168, 171, 174, 177],
+ [180, 183, 186, 189, 192, 195, 198, 201, 204, 207],
+ [210, 213, 216, 219, 222, 225, 228, 231, 234, 237],
+ [240, 243, 246, 249, 252, 255, 258, 261, 264, 267],
+ [270, 273, 276, 279, 282, 285, 288, 291, 294, 297]], dtype=int32)
+ """
+ m[:] = m + m + m
+ return m

0 comments on commit 9b0fc9e

Please sign in to comment.