我创建了一个函数 enc()
def enc():
password = bytes('asd123','utf-8')
salt = bytes('asd123','utf-8')
kdf = PBKDF2HMAC(
algorithm=hashes.SHA256(),
length=32,
salt=salt,
iterations=10000,
backend=default_backend())
key = base64.urlsafe_b64encode(kdf.derive(password))
f = Fernet(key)
for file in files:
with open(file,'rb') as original_file:
original = original_file.read()
encrypted = f.encrypt(original)
with open (file,'wb') as encrypted_file:
encrypted_file.write(encrypted)
它遍历文件中的每个文件并对其进行加密。files = ['D:/folder/asd.txt',
'D:/folder/qwe.mp4',
'D:/folder/qwe.jpg']
我想使用多线程或多处理来使其更快。是否可以?需要一些代码帮助。
我试过多线程
thread = threading.Thread(target=enc)
thread.start()
thread.join()
但它似乎并没有提高速度或时间。我需要一些帮助来实现多处理。谢谢。
最佳答案
线程不是 CPU 密集型任务的最佳候选,除非任务正在执行,例如,由释放全局解释器锁的 C 语言库例程执行。无论如何,除非您并行运行多个进程,否则您肯定会通过多线程或多处理获得任何性能提升。
假设您有 N 个任务和 M 个处理器来处理这些任务。如果任务是没有 I/O 的纯 CPU(不完全是您的情况),那么启动多于 M 个进程来处理您的 N 个任务并没有优势,为此,多处理池是理想的情况。当 CPU 和 I/O 混合使用时,池大小大于 M 可能是有利的,如果 I/O 很多而 CPU 很少,则池大小甚至可能大到 N。但在那种情况下,实际使用多线程池和多处理池(大小为 M)的组合会更好,其中多线程池用于所有 I/O 工作,多处理池用于 CPU 计算。以下代码显示了该技术:
from multiprocessing.pool import Pool, ThreadPool
from multiprocessing import cpu_count
from functools import partial
def encrypt(key, b):
f = Fernet(key)
return f.encrypt(b)
def enc(key, process_pool, file):
with open(file,'rb') as original_file:
original = original_file.read()
encrypted = process_pool.apply(encrypt, args=(key, original,))
with open (file,'wb') as encrypted_file:
encrypted_file.write(encrypted)
def main():
password = bytes('asd123','utf-8')
salt = bytes('asd123','utf-8')
kdf = PBKDF2HMAC(
algorithm=hashes.SHA256(),
length=32,
salt=salt,
iterations=10000,
backend=default_backend())
key = base64.urlsafe_b64encode(kdf.derive(password))
files = ['D:/folder/asd.txt',
'D:/folder/qwe.mp4',
'D:/folder/qwe.jpg']
# compute number of processes in our pool
# the lesser of number of files to process and the number of cores we have:
pool_size = min(cpu_count(), len(files))
# create process pool:
process_pool = Pool(pool_size)
# create thread pool:
thread_pool = ThreadPool(len(files))
worker = partial(enc, key, process_pool)
thread_pool.map(worker, files)
if __name__ == '__main__':
main()
评论 无论如何,重点是:假设您有 30 个文件和 4 个内核,而不是 3 个文件。 @anarchy 发布的解决方案将启动 30 个进程和计算
f
30 次但实际上只能有效利用 4 个处理器来并行计算 f
并进行加密。我的解决方案将使用 30 个线程进行 I/O,但只启动 4 个进程,因此计算 f
只有 4 次。您节省了创建 f
的 26 个进程和 26 个计算。那是没用的。除非您有固态驱动器,否则线程数少于 30 甚至可能更好,因为您的所有线程都在与同一个驱动器竞争,并且 (1) 每个文件可能位于驱动器上完全不同的位置并执行并发 I/O 针对此类文件可能会适得其反,并且 (2) 任何特定驱动器都可以实现一些最大吞吐量。
所以也许我们应该有:
thread_pool = ThreadPool(max(len(files), MAX_THREADS))
哪里MAX_THREADS
设置为适合您的特定驱动器的某个最大值。更新
现在昂贵的计算
key
只做一次。
关于python - 用于加密多个文件的多线程或多处理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69872049/