python - 如何生成一个计数器来查找具有 9 个前导零的哈希值

标签 python multithreading hash mining

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

为了更快,我使用了 Pool 类中的 map() 来使其在所有核心上运行,但如果我传递的 block 大于范围 (99999999),则会出现问题

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(sys.maxsize) 我会得到一个 MemoryError (我知道,因为我不知道)有足够的 RAM,很少有),但我想将 range() 生成的列表分成 block 。 这是可能的还是我应该尝试不同的方法?

最佳答案

嗨,Alin,欢迎来到 stackoverflow。

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

关于代码的 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 的内存,和newHash可以重用,循环比函数便宜,而且只 number_of_processes必须进行函数调用,并且简单地忘记了无趣的结果。

一个可能的缺点是,计数器是完全独立的,每个进程都会精确地执行1/number_of_processes整体工作的效率,即使有些工作比其他工作更快。最终,程序的速度与最慢的进程一样快。我没有测量它,但我想这是一个相当理论的问题。

希望有帮助!

关于python - 如何生成一个计数器来查找具有 9 个前导零的哈希值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56587410/

相关文章:

python - 使用 Python 提取(而不是读取)大型 gzip 文件

python - 使用 Kaleido 导出 Plotly 图表不起作用?

C# 延迟写入 XML

c++ - 无限等待条件变量

Python一致性哈希替换

javascript - javascript 中是否有生成 hash_hmac 代码的方法。 (就像 php 中的 hash_hmac 一样)

python - 如何使用 Python 从 fft-spectrum 创建声音文件?

android - 处理程序是否是线程,具有处理程序和线程的Looper的作用是什么?

jquery - 单击带有哈希标签的链接时强制刷新

python - 类型错误 : 'float' object cannot be interpreted as an integer ( python 3. 4 版本)