Multithreading veya multiprocessing ile veri işlemek

Arkadaşlar elimizde şöyle bir kodumuz var
Ama bilgisayarda işlenmesi günlerce hatta beilki aylarca sürecek gibi görünüyor
Bunu hızlandırmak istiyoruz

Bilgisayarımız Hp Omen i7 7g
8 çekirdekli ve 16gb ram
C sürücüsü 120gb ssd (windows 10 burada yüklü)
D sürücüsü 1tb hdd

Kodumuzu Visual Studio Code - Python üzerinden çalıştırıyoruz
Lakin dikkat ettik ki program cpu’nun sadece %10 kullanıyor

Sistem ayarlarından 8 çekirdeği aktif ettik
ama hiçbir değişiklik yok hala 1 çekirdek kullanılıyor gibi

Biraz araştırma yapınca bunun için Multi Thread ve/veya Multi Process kullanmamız gerektiğini öğrendik
Ama bunları kodumuza uygulayamadık
Yardımcı olabilecek varsa müteşekkir oluruz.

from time import process_time
import bitcoin

 # Bu sadece compressed adresleri buluyor

filehandle1 = open('file1.txt', mode="r") # First file
filehandle2 = open('file2.txt', mode="r") # Second file
filehandle3 = open('file3.txt', mode="r") # Check for combine
filehandle4 = open('file4.txt', 'w') # Equal list file

print("Wait for counting records first file...")
filecount = len(filehandle1.readlines())
filehandle1.seek(0)

count =0
t1_start = process_time() 


def convert_key(kod) :
    valid_private_key = False

    while not valid_private_key:
        private_key = kod
        decoded_private_key = bitcoin.decode_privkey(private_key, 'hex')
        valid_private_key = 0 < decoded_private_key < bitcoin.N
        
    
    compressed_private_key = private_key + '01'
    wif_compressed_private_key = bitcoin.encode_privkey(bitcoin.decode_privkey(compressed_private_key, 'hex'), 'wif')
    public_key = bitcoin.fast_multiply(bitcoin.G, decoded_private_key)
    
    (public_key_x, public_key_y) = public_key
    if (public_key_y % 2) == 0:
        compressed_prefix = '02'
    else:
        compressed_prefix = '03'
    hex_compressed_public_key = compressed_prefix + bitcoin.encode(public_key_x, 16)
    
    return  bitcoin.pubkey_to_address(public_key)
    
def convert_key_compressed(kod) :
    valid_private_key = False

    while not valid_private_key:
        private_key = kod
        decoded_private_key = bitcoin.decode_privkey(private_key, 'hex')
        valid_private_key = 0 < decoded_private_key < bitcoin.N
        
    
    compressed_private_key = private_key + '01'
    wif_compressed_private_key = bitcoin.encode_privkey(bitcoin.decode_privkey(compressed_private_key, 'hex'), 'wif')
    public_key = bitcoin.fast_multiply(bitcoin.G, decoded_private_key)
    
    (public_key_x, public_key_y) = public_key
    if (public_key_y % 2) == 0:
        compressed_prefix = '02'
    else:
        compressed_prefix = '03'
    hex_compressed_public_key = compressed_prefix + bitcoin.encode(public_key_x, 16)
    
    return bitcoin.pubkey_to_address(hex_compressed_public_key)


while True:
    line1 = filehandle1.readline()
    count = count+1
    if not line1:
        break
    
    while True:
        line2 = filehandle2.readline()

        if not line2:
            filehandle2.seek(0)
            break
        # Compressed Coin Check/   To check coin adress use coin_adress() here 
        
        
        try:
            compare_key_compressed = convert_key_compressed(line1.strip()+line2.strip())
        except:
            pass
             
        while True:
            line3 =  filehandle3.readline()
         
            if not line3:
                filehandle3.seek(0)
                break
            #print(line3, compare_key, compare_key_compressed)
            #input()
            if (line3.strip() == compare_key_compressed.strip() ) :
                filehandle4.write(line1.strip()+line2.strip()+' : ')
                filehandle4.write(line3.rstrip()+'\n')
     
    print("Processing: %"+"%0.6f"% ((count/filecount)*100))
    
t1_stop = process_time()
print("Elapsed time in seconds:", t1_stop-t1_start)

filehandle1.close()
filehandle2.close()
filehandle3.close()
filehandle4.close()
1 Beğeni

3 dosyayı da iletirseniz boş zamanlarımda bakmaya çalışırım

Teşşekkür ederim

4 dosyamızda burada

Ama bunlar numune dosyalar

Asıl dosylar çok daha büyük

Örnek Dosyalar

1 Beğeni

Biraz seyredip sonra fikrimi söylesem olur mu?

200

10 milyon X 10 bin X karşılaştırılacak dosya kayıt sayısı kadar iterasyon ;

Haliyle insan yaklaşımları merak ediyor.

3 Beğeni

Dosyanın küçük bir bölümünü Buradan indirebilirsiniz zaten bunun bile işlenmesi başlı başına günlerce sürüyor

1 Beğeni

Kırpılmamış versiyonunda bu dosyaların boyutları ne kadar?

Bunun yaklaşık 100 katı ama kombinasyon yapılırsa 10.000 kat olur

Multithreading işe yaramaz, GIL multithreading’i CPU bound işlemler için kullanılamaz hale getiriyor.

Bu kadar uzun sürecek bir işlem için benim önceliğim algoritmayı optimize etmek ve kullanabileceğim en hızlı kütüphaneyi bulmak olurdu.


Burada potansiyel bir sonsuz döngü var gibi duruyor.

1 Beğeni

Evvela yardımseverliğiniz için teşekkür ederiz

Blok-alıntı

Sizce en uygun ve hızlı kütüphaneyi nasıl bulabiliriz

Blok-alıntı

Bu döngüye öneriniz nedir sizce ne yapabiliriz ?

Kodu PyPI’deki birkaç farklı bitcoin kütüphanesini kullanarak yazıp sonuçları karşılaştırabilirsiniz. Başka bir dilin kütüphanelerini de deneyebilirsiniz.

Ne yapmaya çalıştığınızı bilmiyorum ki bir öneride bulunayım.

Yukarıdaki linkte bulunan dosyalar elimizdeki dosyaların bir bölümünü oluşturuyor
birinci dosyadaki satırlar ile ikinci dosyadaki satırların kombinasyonunu yapınca elimizde 16 basamaklı hex kodları oluşuyor
hex kodlarını wif adres haline çevirip üçüncü dosyadaki adreslerle çakıştıryoruz aynı olanları dördüncü dosyaya yazdırıyoruz
şuan kodumuz çalışıyor bunda bir problem yok tek sıkıntımız istediğimiz hızda çalıştıramamız

from time import process_time
import bitcoin

 # Bu sadece compressed adresleri buluyor

filehandle1 = open('file1.txt', mode="r") # First file
filehandle2 = open('file2.txt', mode="r") # Second file
filehandle3 = open('file3.txt', mode="r") # Check for combine
filehandle4 = open('file4.txt', 'w') # Equal list file

print("Wait for counting records first file...")
filecount = len(filehandle1.readlines())
filehandle1.seek(0)

count =0
t1_start = process_time() 


def convert_key(kod) :
    valid_private_key = False

    while not valid_private_key:
        private_key = kod
        decoded_private_key = bitcoin.decode_privkey(private_key, 'hex')
        valid_private_key = 0 < decoded_private_key < bitcoin.N
        
    
    compressed_private_key = private_key + '01'
    wif_compressed_private_key = bitcoin.encode_privkey(bitcoin.decode_privkey(compressed_private_key, 'hex'), 'wif')
    public_key = bitcoin.fast_multiply(bitcoin.G, decoded_private_key)
    
    (public_key_x, public_key_y) = public_key
    if (public_key_y % 2) == 0:
        compressed_prefix = '02'
    else:
        compressed_prefix = '03'
    hex_compressed_public_key = compressed_prefix + bitcoin.encode(public_key_x, 16)
    
    return  bitcoin.pubkey_to_address(public_key)
    
def convert_key_compressed(kod) :
    valid_private_key = False

    while not valid_private_key:
        private_key = kod
        decoded_private_key = bitcoin.decode_privkey(private_key, 'hex')
        valid_private_key = 0 < decoded_private_key < bitcoin.N
        
    
    compressed_private_key = private_key + '01'
    wif_compressed_private_key = bitcoin.encode_privkey(bitcoin.decode_privkey(compressed_private_key, 'hex'), 'wif')
    public_key = bitcoin.fast_multiply(bitcoin.G, decoded_private_key)
    
    (public_key_x, public_key_y) = public_key
    if (public_key_y % 2) == 0:
        compressed_prefix = '02'
    else:
        compressed_prefix = '03'
    hex_compressed_public_key = compressed_prefix + bitcoin.encode(public_key_x, 16)
    
    return bitcoin.pubkey_to_address(hex_compressed_public_key)


while True:
    line1 = filehandle1.readline()
    count = count+1
    if not line1:
        break
    
    while True:
        line2 = filehandle2.readline()

        if not line2:
            filehandle2.seek(0)
            break
        # Compressed Coin Check/   To check coin adress use coin_adress() here 
        
        
        try:
            compare_key_compressed = convert_key_compressed(line1.strip()+line2.strip())
        except:
            pass
             
        while True:
            line3 =  filehandle3.readline()
         
            if not line3:
                filehandle3.seek(0)
                break
            #print(line3, compare_key, compare_key_compressed)
            #input()
            if (line3.strip() == compare_key_compressed.strip() ) :
                filehandle4.write(line1.strip()+line2.strip()+' : ')
                filehandle4.write(line3.rstrip()+'\n')
     
    print("Processing: %"+"%0.6f"% ((count/filecount)*100))
    
t1_stop = process_time()
print("Elapsed time in seconds:", t1_stop-t1_start)

filehandle1.close()
filehandle2.close()
filehandle3.close()
filehandle4.close()

Ekrem bey bir gelişme kaydedebildiniz mi?
Var mı bir çözüm öneriniz?

Hız konusunda genel geçer bir şeyler söylemiştim zaten. Onun dışında kendim bir deneme yapmadım.

valid_private_key'in değeri False ise, yani private key geçerli değilse sonsuz bir döngüye girmek yerine fonksiyondan key’in geçerli olmadığını ileten bir değer döndürebilir veya bir hata yükseltebilirsiniz.

Yeterince çekirdek yedim. :slight_smile:

Şimdi bir kaç ipucu vermeye çalışayım.

Aslında konuyu elimizde çok fazla veri var dediğinizde;

Aslında sorunu doğru tanımlamak çözümün yarısı olmuştur demek yetmez. Sorunu doğru tanımlarsanız çözüm de kendiliğinden gelir.

Elinizdeki iki parçalı dosyaları öncelikle birleştirin. Ayrı ayrı parçalar halinde tutmanızın hiç bir anlamı yok.

Sonra verilerinizi sıralayın.

Her türlü karşılaştırma algoritmasından öncelikle verileri sıralamak size arama algoritmalarını uygularken fayda sağlayacaktır.

Yani bazı değerleri aramaya dosyanın en başından başlamanıza gerek kalmayacak hızda artış sağlayacaktır.

Eğitimlerde ve çeşitli kurslarda arama algoritmaları anlatılırken öncelikle sıralama algoritmaları öğretilir, çünkü sıralanmış bir veri üzerinde arama yapmak daha kolaydır.

Bu nedenle itereasyon sayınızın fazlalığını hatırlattım.

10 milyon x 10 bin x karşılaştıracak dosyadaki kayıt sayısı konusu bundan önemli.

Ama sıralanmış bir dosyada ikili arama (binary search) yaparsanız, iterasyon sayısı azalacaktır.

Bu anlamlı miktarda hızda iyileşme sağlayacaktır.

Ama asıl burada hızı etkileyen faktör, dosya okuma yazma zamanlarıdır.

Dosya okuma zamanlarını azaltmak tartışmaya açık bir konu. Normal bir sabit diskte (HDD) sıralı erişim dışında bir şansınız olmadığından, okuma yazma konusunda çoklu process yada çoklu işlemenin bir faydası olacağını düşünmüyorum.

Canım sıkıp da bu konuda performans analizi yapar mıyım, belki analiz etmek eğlenceli olabilir.

Ama belki SDD lerede çoklu erişimin bir yolu var mıdır diye de şöyle bir literatüre bakıyorum. (ReadFileScatter anahtar aranacak kelimeniz olsun.)

Dahası, TXT dosyalar, ikili dosylar gibi olmadıklarından gereğinden fazla yer kalplıyor, aslında dosyaları binary olarak kaydetmek daha az yer kaplamalarını sağlayacaktır.

Bir de Windows işletim sistemi, dosyaları, dosyaların belirli bir miktarını sayfa sayfa açıp işleme olanağı sağlayan, api ler sağlar.

File Mapping - Win32 apps | Microsoft Docs

Bu arada, temel bazı kuralları da buraya bırakayım.

Speed Up Python Code | LoginRadius Blog

Mesela for döngülerinden uzak durun, kütüphanlerden faydalanın, çoklu atamaları kullanın, while döngüsünde True yerine 1 kullanın, gibi bir çok basit kural da ufak tefek faydalar sağlar.

Özetle toparlarsak.
Öncelikle dosyalarınız büyükten küçüğe yada küçükten büyüğe bir sıralayın.

Sorting a text file alphabetically (Python) - Stack Overflow

Şu iki parça halindeki 1 ve 2 nolu dosyalarınızı önce binary bir dosyaya birleştirin. Metin dosyaları çok yer kaplıyor.

Python Read A Binary File (Examples) - Python Guides

Gibi bir yerden kullanımlarına bakabilirsiniz.

Ardından dosya karşılaştırmak için şu an kullandığımız metod yerine ikili arama algoritmalarını araştırın.

Bu sayede;

Dosyalar az yer kaplar, arama işlemi daha az iterasyon içerir.

Bunlara rağmen de süre uzun gelirse,

Bu durumda file mapping ile dosyanın belirli kısımlarını ayrı ayrı processlere dağıtıp aramayı eş zamanlı hale getirmeyi deneyebiliriz.

Lafla peynir gemisi yürüttüm.

Kodlarken başımıza ne gelir bilemem.

Fikirlere açığım.

Son bir not daha. Sizin kullandığınız, bit coin kütüphanesi keyleri ne kadar süre tüketerek oluşturuyor onları da ayrıca incelemek gerekebilir.

1 Beğeni

Abi derdi üzüm yemek olan insanlara karşı hep saygımız olmuştur.
Bu nedenle öncelikle sizi tebrik eder arkasından da uzun soluklu çalışma için teşekkür ederiz.
Her zaman dediğimiz gibi
“Biz bize yakışanı yaparız, herkeste kendine yapar”