首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何生成计数器以查找带有9个前导零的散列

如何生成计数器以查找带有9个前导零的散列
EN

Stack Overflow用户
提问于 2019-06-13 19:30:21
回答 1查看 1.2K关注 0票数 2

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

为了更快地实现这一点,我使用了Pool类中的map()来使它在我的所有内核上运行,但是如果我传递一个大于范围(99999999)的块,就会有一个问题。

代码语言:javascript
复制
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 (我知道,因为我没有足够的内存,很少有),但是我想将range()生成的列表分成块。这是可能的还是我应该尝试另一种方法?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-06-14 00:48:02

你好,阿林,欢迎来到堆栈溢出。

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

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

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

但是,我想提出一种不同的解决方案,它解决了这两个问题,非常方便内存,运行速度更快(在N<10测试后我认为是这样),作为maxtasksperchild选项的解决方案:

代码语言:javascript
复制
#!/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]的第二个进程等等。

这种方法的优点是:在than循环的每一次迭代中,都可以重用hashnewHash的内存,循环比函数便宜,只需进行number_of_processes函数调用,就会忘记毫无意义的结果。

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

希望这能帮上忙!

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56587410

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档