繁体   English   中英

用于加密多个文件的多线程或多处理

[英]multithreading or multiprocessing for encrypting multiple files

我创建了一个函数 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 次。 您无需创建 26 个进程和 26 个无用的f计算。

除非您有固态驱动器,否则线程数少于 30 甚至可能更好,因为您的所有线程都在与同一个驱动器竞争,并且 (1) 每个文件可能位于驱动器上完全不同的位置并执行并发 I/ O 针对此类文件可能会适得其反,并且 (2) 任何特定驱动器都可以实现一些最大吞吐量。

所以也许我们应该有:


    thread_pool = ThreadPool(max(len(files), MAX_THREADS))

其中MAX_THREADS设置为适合您的特定驱动器的某个最大值。

更新

现在key的昂贵计算只完成一次。

你需要重新设计你的函数。

Python 不够聪明,无法知道您需要多处理代码的哪一部分。

很可能是 for 循环正确,您希望并行加密文件。 所以你可以尝试这样的事情。

定义每个循环需要运行的函数,然后在外面创建for循环。 然后像这样使用多处理。

import multiprocessing

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)

def enc(file):
    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)
    

if __name__ == '__main__':
    jobs = []
    for file in files:
        p = multiprocessing.Process(target=enc, args=(file,))
        jobs.append(p)
        p.start()

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM