如何生成一个用于查找具有9个前导零的哈希的计数器

2024-10-01 19:19:58 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在尝试创建一个函数,它将使用带有9个前导零的sha1算法生成哈希。散列是基于一些随机数据的,就像在并发挖掘中一样,我只想在哈希函数中使用的字符串中添加1。在

为了更快,我使用了Pool类中的map()使其在我所有的核心上运行,但是如果我传递的块大于range(999999999),我就有一个问题

def computesha(counter):
        hash = 'somedata'+'otherdata'+str(counter)
        newHash = hashlib.sha1(hash.encode()).hexdigest()     
        if newHash[:9] == '000000000':       
            print(str(newHash))
            print(str(counter))
            return str(newHash), str(counter)   

if __name__ == '__main__':

    d1 = datetime.datetime.now()
    print("Start timestamp" + str(d1))

    manager = multiprocessing.Manager()
    return_dict = manager.dict()

    p = Pool()
    p.map(computesha, range(sys.maxsize) )
    print(return_dict)
    p.close()
    p.join()

    d2 = datetime.datetime.now()  
    print("End timestamp " + str(d2))
    print("Elapsed time: " + str((d2-d1)))    

我想创建一个类似于全局计数器的东西,当它运行多线程时,把它输入到函数中,但是如果我尝试range(系统最大大小)我得到一个MemoryError(我知道,因为我没有足够的内存,很少有内存),但是我想把range()生成的列表分成块。 这是可能的还是我应该尝试另一种方法?在


Tags: 函数mapdatetimereturncounterrangesha1dict
1条回答
网友
1楼 · 发布于 2024-10-01 19:19:58

嗨,阿林,欢迎来到stackoverflow。在

首先,是的,全局计数器是可能的。E、 带有一个multiprocessing.Queue或一个multiprocessing.Value传递给工人的g。但是,从全局计数器获取一个新的数字将导致锁定(并可能等待)计数器。这是可以而且应该避免的,因为您需要进行大量的计数器查询。我在下面提出的解决方案是通过安装几个本地计数器来避免全局计数器,这些计数器就像一个全局计数器一样一起工作。在

关于代码的RAM消耗,我看到两个问题:

  1. computesha大多数时候返回一个None值。这将进入由map创建的迭代器(即使您没有指定map的返回值)。这意味着迭代器比需要的大得多。在
  2. 一般来说,进程的RAM在进程完成后被释放。你的进程启动了很多任务,它们都保留了自己的内存。一个可能的解决方案是maxtasksperchild选项(请参阅multiprocessing.pool.Pool的文档)。当您将此选项设置为1000时,它将在1000个任务之后关闭进程并创建一个新的进程,从而释放内存。在

但是,我想提出一个不同的解决方案,它可以解决这两个问题,非常有利于内存并且运行速度更快(在N<;10次测试之后,我觉得是这样)作为带有maxtasksperchild选项的解决方案:

#!/usr/bin/env python3
import datetime
import multiprocessing
import hashlib
import sys

def computesha(process_number, number_of_processes, max_counter, results):
    counter = process_number # every process starts with a different counter
    data = 'somedata' + 'otherdata'

    while counter < max_counter: #stop after max_counter jobs have been started
        hash = "".join((data,str(counter)))
        newHash = hashlib.sha1(hash.encode()).hexdigest()
        if newHash[:9] == '000000000':
            print(str(newHash))
            print(str(counter))

            # return the results through a queue
            results.put((str(newHash), str(counter)))
        counter += number_of_processes # 'jump' to the next chunk

if __name__ == '__main__':
    # execute this file with two command line arguments:
    number_of_processes = int(sys.argv[1])
    max_counter = int(sys.argv[2])

    # this queue will be used to collect the results after the jobs finished
    results = multiprocessing.Queue()

    processes = []
    # start a number of processes...
    for i in range(number_of_processes):
        p = multiprocessing.Process(target=computesha, args=(i,
                                                             number_of_processes,
                                                             max_counter,
                                                             results))
        p.start()
        processes.append(p)

    # ... then wait for all processes to end
    for p in processes:
        p.join()

    # collect results
    while not results.empty():
        print(results.get())
    results.close()

此代码生成所需的number_of_processes,然后调用computesha函数。如果number_of_processes=8,则第一个进程计算计数器值[0,8,16,24,...]的哈希值,第二个进程计算[1,9,17,25]的哈希值,依此类推。在

这种方法的优点是:在while循环的每次迭代中,hash和{}的内存可以重用,循环比函数便宜,只需调用number_of_processes函数,而不感兴趣的结果则被简单地遗忘。在

一个可能的缺点是,计数器是完全独立的,并且每个进程都将完成全部工作的1/number_of_processes,即使某些进程比其他进程快。最终,程序的速度和最慢的过程一样快。我没有测量,但我想这是一个相当理论上的问题。在

希望有帮助!在

相关问题 更多 >

    热门问题