我正在尝试创建一个函数,该函数将使用具有9个前导零的sha1算法生成哈希。哈希是基于一些随机数据的,就像在并发挖掘中一样,我只想向哈希函数中使用的字符串加1。
为了更快,我使用Pool类中的map()使其在我的所有内核上运行,但是如果传递的块大于range(99999999),则会出现问题
return builder.routes()
.route("rewrite_route", r -> r.path("/**")
.filters(f -> f.filter(filter)
.rewritePath("/(?<segment>.*)", "abc//$\\{segment}")
.removeRequestHeader("X-Forwarded-Proto")
.addRequestHeader("authorization","")
.addRequestHeader("apiKey", "qwerwqrw")
)
.uri("https://somedomian"))
.build();
}
我想创建一个类似于全局计数器的东西,以便在它运行多线程时将其输入到函数中,但是如果我尝试使用range(sys.maxsize),则会收到MemoryError(我知道,因为我没有有足够的RAM,很少有),但是我想将range()生成的列表拆分为多个块。 这有可能还是我应该尝试其他方法?
答案 0 :(得分:0)
嗨Alin,欢迎来到stackoverflow。
首先,是的,可以使用全局计数器。例如,将multiprocessing.Queue或multiprocessing.Value传递给工作人员。但是,从全局计数器中获取新的数字将导致锁定(并可能等待)计数器。可以而且应该避免这种情况,因为您需要进行大量的计数器查询。我下面提出的解决方案通过安装多个本地计数器来避免全局计数器,这些本地计数器可以像一个全局计数器一样协同工作。
关于代码的RAM消耗,我看到两个问题:
computesha
大部分时间返回None
值。这将进入由map
创建的迭代器中(即使您未分配map
的返回值)。这意味着,迭代器比必要的要大得多。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
,即使某些进程比其他进程更快。最终,该程序与最慢的进程一样快。我没有测量它,但我想这是一个相当理论上的问题。
希望有帮助!