python - مكتبة - الحديثة، عالية الأداء ازهر مرشح في بايثون؟




مكتبة اكواد بايثون (5)

أنا أبحث عن تنفيذ جودة الإنتاج مرشح ازهر في بايثون للتعامل مع أعداد كبيرة إلى حد ما من البنود (ويقول 100M إلى 1B البنود مع 0.01٪ معدل إيجابي كاذبة).

بيبلوم هو خيار واحد ولكن يبدو أن تبين عمرها كما يلقي ديبريكاتيونوارنينغ أخطاء على بيثون 2.5 على أساس منتظم. لديه جو غريغوريو أيضا التنفيذ .

المتطلبات هي أداء بحث سريع والاستقرار. أنا أيضا مفتوحة لإنشاء واجهات بايثون جيدة ج / c ++ تطبيقات خاصة، أو حتى ل جيثون إذا كان هناك تنفيذ جافا جيدة.

عدم وجود ذلك، أي توصيات بشأن تمثيل متجه صفيف / بت قليلا التي يمكن التعامل مع ~ 16E9 بت؟


انظر إلى وحدة الصفيف .

class Bit( object ):
    def __init__( self, size ):
        self.bits= array.array('B',[0 for i in range((size+7)//8)] )
    def set( self, bit ):
        b= self.bits[bit//8]
        self.bits[bit//8] = b | 1 << (bit % 8)
    def get( self, bit ):
        b= self.bits[bit//8]
        return (b >> (bit % 8)) & 1

فويو، كل من //8 و % 8 عمليات يمكن استبدالها مع >>3 &0x07 . وهذا قد يؤدي إلى سرعة أفضل قليلا في خطر بعض الغموض.

أيضا، تغيير 'B' و 8 إلى 'L' و 32 يجب أن يكون أسرع على معظم الأجهزة. [التغيير إلى 'H' و 16 قد يكون أسرع على بعض الأجهزة، ولكن من المشكوك فيه.]


في نهاية المطاف وجدت بيبلومفيلترماب . أنا لم تستخدمه، ولكن يبدو أنها تناسب مشروع القانون.


لقد ذهبت مؤخرا إلى هذا المسار أيضا. على الرغم من أنه يبدو أن طلبي كان مختلفا قليلا. كنت مهتما في تقريب عمليات مجموعة على عدد كبير من السلاسل.

يمكنك إجراء الملاحظة الرئيسية التي تتطلب ناقلات بت سريع . اعتمادا على ما تريد وضعه في مرشح ازهر الخاص بك، قد تحتاج أيضا إلى إعطاء بعض التفكير لسرعة خوارزمية التجزئة (ق) المستخدمة. قد تجد هذه المكتبة مفيدة. قد تحتاج أيضا إلى العبث مع تقنية الرقم العشوائي المستخدمة أدناه أن تجزئة مفتاح الخاص بك مرة واحدة فقط.

من حيث تنفيذ مجموعة صفيف غير جافا:

أنا بنيت بلدي ازهر تصفية باستخدام بيتفيكتور . قضيت بعض الوقت التنميط وتحسين المكتبة والمساهمة مرة أخرى بقع بلدي ل آفي. انتقل إلى هذا الرابط بيتفيكتور والتمرير لأسفل إلى الاعتراف في v1.5 لمعرفة التفاصيل. في النهاية، أدركت أن الأداء لم يكن هدفا لهذا المشروع وقرر عدم استخدامه.

وهنا بعض التعليمات البرمجية كان الكذب حولها. أنا قد وضعت هذا على جوجل كود في بيثون-بلوم. اقتراحات ترحيب.

from BitVector import BitVector
from random import Random
# get hashes from http://www.partow.net/programming/hashfunctions/index.html
from hashes import RSHash, JSHash, PJWHash, ELFHash, DJBHash


#
# [email protected] / www.asciiarmor.com
#
# copyright (c) 2008, ryan cox
# all rights reserved 
# BSD license: http://www.opensource.org/licenses/bsd-license.php
#

class BloomFilter(object):
    def __init__(self, n=None, m=None, k=None, p=None, bits=None ):
        self.m = m
        if k > 4 or k < 1:
            raise Exception('Must specify value of k between 1 and 4')
        self.k = k
        if bits:
            self.bits = bits
        else:
            self.bits = BitVector( size=m )
        self.rand = Random()
        self.hashes = []
        self.hashes.append(RSHash)
        self.hashes.append(JSHash)
        self.hashes.append(PJWHash)
        self.hashes.append(DJBHash)

        # switch between hashing techniques
        self._indexes = self._rand_indexes
        #self._indexes = self._hash_indexes

    def __contains__(self, key):
        for i in self._indexes(key): 
            if not self.bits[i]:
                return False    
        return True 

    def add(self, key):
        dupe = True 
        bits = []
        for i in self._indexes(key): 
            if dupe and not self.bits[i]:
                dupe = False
            self.bits[i] = 1
            bits.append(i)
        return dupe

    def __and__(self, filter):
        if (self.k != filter.k) or (self.m != filter.m): 
            raise Exception('Must use bloom filters created with equal k / m paramters for bitwise AND')
        return BloomFilter(m=self.m,k=self.k,bits=(self.bits & filter.bits))

    def __or__(self, filter):
        if (self.k != filter.k) or (self.m != filter.m): 
            raise Exception('Must use bloom filters created with equal k / m paramters for bitwise OR')
        return BloomFilter(m=self.m,k=self.k,bits=(self.bits | filter.bits))

    def _hash_indexes(self,key):
        ret = []
        for i in range(self.k):
            ret.append(self.hashes[i](key) % self.m)
        return ret

    def _rand_indexes(self,key):
        self.rand.seed(hash(key))
        ret = []
        for i in range(self.k):
            ret.append(self.rand.randint(0,self.m-1))
        return ret

if __name__ == '__main__':
    e = BloomFilter(m=100, k=4)
    e.add('one')
    e.add('two')
    e.add('three')
    e.add('four')
    e.add('five')        

    f = BloomFilter(m=100, k=4)
    f.add('three')
    f.add('four')
    f.add('five')
    f.add('six')
    f.add('seven')
    f.add('eight')
    f.add('nine')
    f.add("ten")        

    # test check for dupe on add
    assert not f.add('eleven') 
    assert f.add('eleven') 

    # test membership operations
    assert 'ten' in f 
    assert 'one' in e 
    assert 'ten' not in e 
    assert 'one' not in f         

    # test set based operations
    union = f | e
    intersection = f & e

    assert 'ten' in union
    assert 'one' in union 
    assert 'three' in intersection
    assert 'ten' not in intersection
    assert 'one' not in intersection

أيضا، في حالتي وجدت أنه من المفيد أن يكون لها وظيفة العد_bits أسرع ل بيتفيكتور. إسقاط هذا الرمز في بيتفيكتور 1.5 ويجب أن تعطيك طريقة العد قليلا أكثر أداء:

def fast_count_bits( self, v ):
    bits = (
            0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4,
            1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
            1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
            2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
            1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
            2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
            2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
            3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
            1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
            2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
            2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
            3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
            2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
            3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
            3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
            4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8 )

    return bits[v & 0xff] + bits[(v >> 8) & 0xff] + bits[(v >> 16) & 0xff] + bits[v >> 24]

لقد طرحت تطبيق تصفية بيثون ازهر في http://stromberg.dnsalias.org/~strombrg/drs-bloom-filter/

انها في الثعبان النقي، لديه وظائف التجزئة جيدة، والاختبارات الآلي جيدة، ومجموعة مختارة من الخلفيات (القرص، صفيف، مماب، وأكثر) وسيطات أكثر بديهية إلى __init__ الأسلوب، حتى تتمكن من تحديد عدد مثالي من العناصر ومعدل الخطأ الأقصى المطلوب ، بدلا من أثيري إلى حد ما، داتاستروتور هيكل محدد.






bloom-filter