1

如果我运行这个脚本

$ seq 1 4 | taskset -c 0-3 parallel -j4 -u <my_bash_script.sh>

<my_bash_script.sh>然后包含在多个 cpu 而不是一个 cpu 上运行的每个 python 进程。python 函数同时使用 numpy 和 pytorch。因此,该选项taskset -c 0-4强加了 CPU 的最大数量,但它不保证每个进程将被限制为一个 CPU。

我试过了

$ export OPENBLAS_NUM_THREADS=1
$ export MKL_NUM_THREADS=1

但它没有用

我还添加到 python 脚本中

import mkl
mkl.set_num_threads(1)

但这没有帮助

4

2 回答 2

1

使用工作槽:

$ seq 1 4 | parallel -j4 -u taskset -c {%} <my_bash_script.sh>

Jobslot 就是为此而设计的:想象一下,你有超过 4 个工作。如果您随后将每 4 个作业分配给 cpu 4,那么您就有可能每 4 个作业都比其他作业短。在这种情况下,即使有更多作业要运行,cpu 4 也会空闲。

Jobslot 不会将每个第 4 个作业传递给 cpu 4。相反,它会查看完成作业的哪个 cpu(或者更确切地说是作业槽),然后在该 cpu 上开始一个新作业。

(另外:由于您正在使用,您应该了解(默认)和(这通常是您在使用时真正想要的)-u之间的区别)。--group--linebuffer-u

于 2020-08-24T06:10:49.123 回答
0

问题是您将可以运行taskset的 CPU 限制为 4 个 CPU。parallel我相当确定 的子进程parallel、它的每个实例my_bash_script.sh及其启动的 Python 进程也将继承同一组 CPU 关联性,因此它们也将能够在您指定的 4 个 CPU 中的任何一个上运行。

我认为,您想要的是将启动的每个 Python 进程限制parallel在不同的 CPU 上,您可以通过tasksetmy_bash_script.sh. 具体来说,不要限制parallel运行位置,而是限制它启动的 Python 进程可以运行的位置,方法将调用包装pythonmy_bash_script.shwith 中taskset。您将一个数字传递给每个调用,my_bash_script.sh以便您可以使用它来为每个python调用计算不同的 CPU(当前您可以使用(($1 - 1)),因为您传入值 1 - 4 但如果您有更多,您需要值 mod 4 或其他东西)。

请注意,我所描述的应该有效,但并不完美。假设您在 CPU 1 上运行进程 1,在 CPU 2 上运行进程 2,等等。如果进程 1 先完成,则没有任何东西在使用 CPU 1,也没有任何东西使用 CPU 1,因为您已将其他进程限制为每个 CPU 1 个。理想情况下,您希望他们能够接管现在空闲的 CPU,但这更复杂。

编辑:@Ole Tang 上面的回答建议使用{%}作业槽,而不是根据您提交任务的顺序将任务分配给 CPU,这有助于(但不能消除)我上面描述的问题。

我想知道你为什么要将它们限制为每个 1 个 CPU。确实,如果同时运行许多线程,内核将尝试对它们进行时间切片以给每个线程平等的资源,这实际上会由于上下文切换、缓存冲突等而损害性能。 OTOH,如上所述,替代方案至少在某些时候可能会让一些 CPU 处于空闲状态,这并不明显最终会给您带来更好的性能。

于 2020-08-23T22:59:18.587 回答