python 파이썬 - 다른 선형 대수 백엔드를 제공하기위한 아키텍처





벡터 내적 (4)


PEP-3141 과 표준 lib 모듈 ABCMeta 확인해야합니다.

ABCMeta를 사용하는 방법에 대한 자세한 설명을 보려면 항상 유용한 PyMOTW 가 좋은 글을 PyMOTW .

파이썬에서 새로운 시스템을 프로토 타이핑하고있다. 기능은 대부분 숫자입니다.

중요한 요구 사항은 각각의 사용자 구현에서 Numpy와 같은 일반 라이브러리에 이르기까지 다양한 선형 대수학 백엔드를 사용할 수 있다는 것입니다. 선형 대수학 구현 (즉, 백엔드)은 인터페이스와 독립적이어야합니다.

나의 초기 건축 시도는 다음과 같다 :

(1) 시스템 인터페이스 정의

>>> v1 = Vector([1,2,3])
>>> v2 = Vector([4,5,6])
>>> print v1 * v2
>>> # prints "Vector([4, 10, 18])"

(2) 백엔드와 독립적으로 해당 인터페이스를 사용할 수 있도록 코드를 구현하십시오

# this example uses numpy as the back-end, but I mean
# to do this for a general back-end
import numpy 
def numpy_array(*args): # creates a numpy array from the arguments
    return numpy.array(*args)

class VectorBase(type):
    def __init__(cls, name, bases, attrs):
        engine = attrs.pop("engine", None)
        if not engine:
            raise RuntimeError("you need to specify an engine")
        # this implementation would change depending on `engine`
        def new(cls, *args):
            return numpy_array(*args)   
        setattr(cls, "new", classmethod(new))

class Vector(object):   
    __metaclass__ = VectorBase        
    # I could change this at run time
    # and offer alternative back-ends
    engine = "numpy"  
    @classmethod
    def create(cls, v):
        nv = cls()
        nv._v = v
        return nv    
    def __init__(self, *args):  
        self._v = None
        if args:
            self._v = self.new(*args)
    def __repr__(self):
        l = [item for item in self._v]
        return "Vector(%s)" % repr(l)
    def __mul__(self, other):
        try:
            return Vector.create(self._v * other._v)
        except AttributeError:
            return Vector.create(self._v * other)
    def __rmul__(self, other):
        return self.__mul__(other)

이 간단한 예제는 다음과 같이 작동합니다. Vector 클래스는 백엔드에서 만든 벡터 인스턴스에 대한 참조를 유지합니다 (이 예에서 numpy.ndarray ). 모든 산술 호출은 인터페이스에 의해 구현되지만 평가는 백엔드로 연기됩니다.

실제로이 인터페이스는 모든 적절한 연산자와 방어기를 백엔드로 오버로드합니다 (이 예에서는 __mul____rmul__ 만 보여 주지만 각 작업마다 동일하게 수행 할 수 있음).

나는 customizability의 교환에 약간의 성과를 풀어 기꺼이한다. 예제가 작동하는 동안에도 제대로 작동하지 않습니다. 많은 생성자 호출로 백 엔드를 손상시킬 수 있습니다! 이것은 다른 metaclass 구현을 요구하며 더 나은 호출 지연을 허용합니다.

그렇다면이 기능을 구현하는 것이 어떻습니까? 시스템의 모든 Vector 인스턴스를 선형 대수학 백엔드와 동질적이고 독립적으로 유지하는 것이 중요하다는 것을 강조 할 필요가 있습니다.




참고로 간단히 NumPy를 구성하여 보통의 ATLAS + LAPACK 대신 Intel 수학 커널 라이브러리 또는 AMD Core Math Library를 사용하도록 구성 할 수 있습니다. 이것은 blas_libs , lapack_libs , library_dirsinclude_dirs 변수를 적절히 설정하여 site.cfg 파일을 만드는 것만 큼 간단합니다. (MKL과 ACML에 대한 이러한 옵션을 설정하는 방법은 Google에서 쉽게 할 수 있습니다.) setup.py 스크립트와 나란히 놓고 평소와 같이 빌드하십시오.

이러한 표준 선형 대수학 라이브러리간에 전환하려면 각각에 대해 다른 NumPy 인스턴스를 만들고 virtualenvs 사용하여 관리 할 수 ​​있습니다.

나는 그것이 당신에게 당신의 자신 만의 수학 라이브러리를 사용할 필요가있는 융통성을주지는 않는다는 것을 알고 있습니다. 아직 살펴 보지는 않았지만, NumPy를 자신의 프론트 엔드를 구축하는 것보다 더 적은 노력으로 맞춤 라이브러리를 구축 할 수있을 것이라고 생각합니다. 특히 광범위한 기능을 유지하려는 경우 더욱 그렇습니다. NumPy / SciPy 구성 요소의




왜 당신의 예제에서 Vector와 같은 "가상"클래스 ( AbstractVector )를 만들지 않고 각 구현에 대해 다른 하위 클래스를 만드는 것이 좋을까요?

Vector = NumPyVector 또는 그런 식으로 엔진을 선택할 수 있습니다.




나는 EigenNT2 에 관해 좋은 점을 들었지만 개인적으로 사용하지는 않았다. Boost.UBLASBoost.UBLAS , 나는 이빨이 약간 길어지고 있다고 생각합니다. NT2의 개발자들은 Boost에 넣으려는 의도로 다음 버전을 개발하고 있습니다.

내 린. alg. 필요성은 4x4 매트릭스의 경우를 벗어나서 확장되지 않으므로 고급 기능에 대해서는 언급 할 수 없습니다. 몇 가지 옵션을 지적하고 있습니다.





python architecture linear-algebra backend metaclass