13

Pythonで新しいシステムのプロトタイプを作成しています。機能はほとんど数値です。

重要な要件は、個々のユーザー実装から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__されますが、すべての操作で同じことが行われることを確認できます)。

カスタマイズ性と引き換えに、パフォーマンスをいくらか失うことをいとわない。私の例は機能しますが、それは正しく感じられません-非常に多くのコンストラクター呼び出しでバックエンドを壊してしまいます!これは別のmetaclass実装を要求し、より良い呼び出し延期を可能にします。

では、この機能を実装することをどのように推奨しますか?Vectorシステムのすべてのインスタンスを均一に保ち、線形代数のバックエンドから独立させることの重要性を強調する必要があります。

4

3 に答える 3

6

PEP-3141と標準のlibモジュールABCMetaをチェックする必要があります。

ABCMetaの使用方法の詳細な説明については、常に役立つPyMOTWにすばらしい記事があります。

于 2011-06-02T06:08:42.367 に答える
3

例のVectorのような「仮想」クラス(AbstractVector)を作成し、実装ごとに異なるサブクラスを作成してみませんか?

エンジンは、Vector = NumPyVectorそのようなことをすることによって選択することができます。

于 2011-06-01T18:12:51.743 に答える
2

参考までに、通常のATLAS + LAPACKの代わりに、IntelのMathKernelLibraryまたはAMDのCoreMathLibraryを使用するようにNumPyを簡単に構成および構築できます。これは、、、、および変数を適切に設定してsite.cfgファイルを作成するのと同じくらい簡単です。(MKLおよびACMLのこれらのオプションの設定の詳細は、簡単にGoogleで確認できます。)スクリプトの横に配置し、通常どおりにビルドします。blas_libslapack_libslibrary_dirsinclude_dirssetup.py

これらの標準的な線形代数ライブラリを切り替えるには、たとえば、それぞれに異なるNumPyのインスタンスを作成し、virtualenvsを使用してそれらを管理します。

独自のカスタム数学ライブラリを使用するために必要な柔軟性が得られないことはわかっていますが、それを捨てると思っただけです。まだ調べていませんが、特に広範な機能を維持したい場合は、独自のフロントエンドを構築するよりも少ない労力でNumPyをカスタムライブラリに対して構築できる可能性があると思います。 NumPy/SciPyの建物の。

于 2011-06-11T20:00:03.593 に答える