这个函数只是获取一个网页并将其生涯到一个当地文件中,轮回多次。无用但直截了当,因此很得当演示。让我们看看基准是什么吧。

此刻,从这两张图表中可以留意到以下几点:
- 在这两种环境下,单个历程的执行时刻都比单个线程长。显然,历程比线程有更多的开销。
- 对付受 CPU 限定的使命,多个历程的机能比多个线程要好。然而,当我们行使 8x 并行化时,这种差别就变得不那么明明晰。因为我的条记本电脑中的处理赏罚器是四核的,因此最多有四个历程可以有用地行使多核。以是当我行使更多的历程时,它的伸缩性就欠好。可是,它如故比线程机能好许多,由于线程基础不能操作多个核。
- 对付 IO 绑定的使命,瓶颈不是 CPU。因此,GIL 带来的凡是限定在这里不合用,多处理赏罚也没有上风。不只云云,线程的轻量级开销现实上使它们比多处理赏罚更快,而且线程始终优于多处理赏罚。
差别、优弱点
- 线程在沟通的内存空间中运行;历程有单独的内存。
- 以前面的概念来看:在线程之间共享工具更轻易,但与此同时,你必需采纳特另外法子来实现工具同步,以确保两个线程不会同时写入统一个工具,而且不会呈现争用环境。
- 因为工具同步增进了编程开销,多线程编程更轻易呈现错误。另一方面,多历程编程很轻易实现。
- 与历程对比,线程的开销更低;天生历程比线程耗费更多的时刻。
- 因为 python 中 GIL 的范围性,线程不能操作多个 CPU 核实现真正的并行。多处理赏罚没有任何这样的限定。
- 历程调治由操纵体系处理赏罚,而线程调治则由 python 表明器完成。
- 子历程是可间断和可终止的,而子线程不是。你必需守候线程终止或插手。
从全部这些接头中,我们可以得出以下结论:
- 线程应该用于涉及 IO 或用户交互的措施。
- 多处理赏罚应该用于 CPU 受限、计较麋集型的措施。
从数据科学家的角度
典范的数据处理赏罚管道可分为以下步调:
- 读取原始数据并存储到主存储器或 GPU 中;
- 行使 CPU 或 GPU 举办计较;
- 将发掘出的信息存储在数据库或磁盘中。
让我们来试探如安在这些使命中引入并行性,从而加速它们的速率。
步调 1 包罗了从磁盘读取数据,因此很明明磁盘 IO 将成为此步调的瓶颈。正如我们所接头的,线程是并行这种操纵的最佳选择。同样,步调 3 也是引入线程的抱负候选步调。
可是,步调 2 包括涉及 CPU 或 GPU 的计较。假如是基于 CPU 的使命,那么行使线程将毫无用处;相反,我们必需举办多处理赏罚。只有这样,我们才气操作 CPU 的多个核并实现并行性。假如这是一个基于 GPU 的使命,由于 GPU 已经在硬件级别实现了一个大局限并行化的系统布局,那么行使正确的接口(库和驱动措施)与 GPU 交互应该可以处理赏罚剩下的工作。

此刻你也许会想,「我的数据管道看起来与此有些差异;我有一些使命并不真正得当这个通用框架。」不外,在这里你应该思量的身分是:
- 你的使命是否有任何情势的 IO
- IO 是否是措施的瓶颈
- 你的使命是否取决于 CPU 的大量计较
思量到这些身分,再加上上面的要点,你应该可以或许做出抉择。其它,请记着,你不必在整个措施中行使单一情势的并行,而是应该在措施的差异部门行使差异的并行。
此刻我们来看看数据科学家也许面对的两个常见场景,以及怎样行使并行计较来加快它们。
场景 1:下载电子邮件
假设你想说明本身创业公司收件箱中的全部电子邮件,并相识其趋势:谁是最频仍的发件人,电子邮件中呈现的最常见要害字是什么,一周中的哪一天或一天中的哪一小时收到的电子邮件最多,等等。虽然,这个项目标第一步是将电子邮件下载到你的计较机上。
起首,让我们按次序举办,而不行使任何并行化。下面是要行使的代码,应该很是简朴明白。有一个下载电子邮件的成果,它以电子邮件 ID 列表作为输入,并按次序下载它们。这个函数一次挪用 100 个电子邮件的 ID 列表。
- import imaplib
- import time
- IMAP_SERVER = 'imap.gmail.com'
- USERNAME = 'username@gmail.com'
- PASSWORD = 'password'
-
- def download_emails(ids):
- client = imaplib.IMAP4_SSL(IMAP_SERVER)
- client.login(USERNAME, PASSWORD)
- client.select()
- for i in ids:
- print(f'Downloading mail id: {i.decode()}')
- _, data = client.fetch(i, '(RFC822)')
- with open(f'emails/{i.decode()}.eml', 'wb') as f:
- f.write(data[0][1])
- client.close()
- print(f'Downloaded {len(ids)} mails!')
-
- start = time.time()
-
- client = imaplib.IMAP4_SSL(IMAP_SERVER)
- client.login(USERNAME, PASSWORD)
- client.select()
- _, ids = client.search(None, 'ALL')
- ids = ids[0].split()
- ids = ids[:100]
- client.close()
-
- download_emails(ids)
- print('Time:', time.time() - start)
所用时刻:35.65300488471985 秒。 (编辑:湖南网)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!
|