Может ли Cython ускорить массив итераций объектов? - PullRequest
9 голосов
/ 21 октября 2010

Я хочу ускорить следующий код, используя cython:

class A(object):
    cdef fun(self):
        return 3


class B(object):
    cdef fun(self):
        return 2

def test():
    cdef int x, y, i, s = 0
    a = [ [A(), B()], [B(), A()]]
    for i in xrange(1000):
        for x in xrange(2):
            for y in xrange(2):
                s += a[x][y].fun()
    return s

Единственное, что приходит на ум, это что-то вроде этого:

def test():
    cdef int x, y, i, s = 0
    types = [ [0, 1], [1, 0]]
    data = [[...], [...]]
    for i in xrange(1000):
        for x in xrange(2):
            for y in xrange(2):
                if types[x,y] == 0:
                   s+= A(data[x,y]).fun()
                else:
                   s+= B(data[x,y]).fun() 
    return s

По сути, решение на C ++будет иметь массив указателей на некоторый базовый класс с виртуальным методом fun(), тогда вы сможете довольно быстро его перебирать.Есть ли способ сделать это, используя python / cython?

Кстати: будет ли быстрее использовать 2D-массив numpy с dtype = object_ вместо списков python?

1 Ответ

7 голосов
/ 22 октября 2010

Похоже, что такой код дает примерно 20-кратное ускорение:

import numpy as np
cimport numpy as np
cdef class Base(object):
    cdef int fun(self):
        return -1

cdef class A(Base):
    cdef int fun(self):
        return 3


cdef class B(Base):
    cdef int fun(self):
        return 2

def test():
    bbb = np.array([[A(), B()], [B(), A()]], dtype=np.object_)
    cdef np.ndarray[dtype=object, ndim=2] a = bbb

    cdef int i, x, y
    cdef int s = 0
    cdef Base u

    for i in xrange(1000):
        for x in xrange(2):
            for y in xrange(2):
                u = a[x,y]                
                s += u.fun()
    return s

Он даже проверяет, что A и B наследуются от Base, возможно, есть способ отключить его в сборках релиза и получить дополнительное ускорение

РЕДАКТИРОВАТЬ: проверка может быть удалена с помощью

u = <Base>a[x,y]
...