我可以使用Raspberry Pi CPU的所有4个内核吗?


11

我想知道是否有一种简单的方法可以“打开”所有100%的CPU,以便我可以更快地运行进程(例如python计算)。

1)这可能吗?

2)是否有简单的方法可以还原到正常状态?

3)如果需要,是否可以使用较少的CPU?

我在想像这样的命令行交互:

pi@raspberry:~ $ sudo turnOnFourCores python run.py


1
简短的答案是“不”
Steve Robillard

16
长答案是“如果就这么简单,那将是默认值”
Shadow

18
无论您的意见是误导,并可能暗示丕具有4个核心,但永远只能使用1更好的答案应该是,所有四个核心ARE已经打开,但Python中(以及任何其他程序,对于这个问题)将只使用更多除非它们是多线程的,否则不超过1个内核。由于全局解释器锁定,即使使用多线程,Python仍然可以有效地使用单核卡住,但这超出了此问题的范围。
Sohcahtoa82

13
需要澄清的是,我认为OP对多核CPU的工作方式存在误解,您的回答只会加剧他们的误解。
Sohcahtoa82

6
使Python程序更快的最简单方法是用编译语言进行重写(或至少使时间紧迫的任务使用ac模块)。
Milliways

Answers:


21

默认情况下,任何计算机都将尝试使用其所有内核。但是,只有在应用程序为多线程时,它才能实现此目的。如果不是(即不使用该threading模块的Python脚本),则最多只能使用一个内核。这相当于四核CPU上CPU的25%。如果您想修改脚本以使用多个内核,则可以将计算分为多个部分,并对其进行多线程处理,如Python文档中所示。

更新:

正如Anon回答的那样,如果不使用Python的GIL(全局解释器锁),这将无法正常工作。这允许任务同时(看似)运行,但不允许代码跨多个内核运行。如果您使用的是用C语言编写的模块(例如numpy),则它们可以允许您使用多个内核来绕过该限制。此外,如果不是这样,Python将提供multiprocessing,它允许您在多个内核上运行任何任务。


该更新-是正确的-解释了为什么答案的第一部分相对于Python是错误的。您只能通过编写模块C或某种编译语言来克服Python的这种局限性,此时,您将不再真正编写Python。如果性能至关重要,那么使用编译语言是正确的答案。(从资源使用的角度来看,多处理并不相同。)
Brick 2005年

4
@Brick需要明确的是,编译语言当然不是正确的进程内多线程的要求。哎呀,甚至Python的GIL都是一个实现细节(对于流行的CPython来说,是允许的)-还有其他将幸福地使用多线程的Python解释器,例如Jython和IronPython。
鲍勃·鲍勃,

4
更令人困惑的是,Python 已被编译。对于CPython,它将编译为在CPython VM中运行的CPython字节码。对于Jython,它被编译为Java字节码,并在JVM中运行。最后,IronPython编译为针对.NET运行时的CIL。因此,“使用一种编译语言”来提高性能并不有意义;)
marcelm

任何计算机都将尽可能尝试使用其所有内核。并非如此,仅在告知时才会使用其所有内核(或执行其他任何操作)。对于经验丰富的人来说,这种区别似乎很明显,甚至是光顾的,但是听起来OP需要意识到它不是自动发生的。
nekomatic

13

我想知道是否有一种简单的方法可以“打开”所有100%的CPU,以便我可以更快地运行进程(例如python计算)。

我认为您的意思不是这样。这不是pi特有的问题,这也是一个逻辑约束。

目前,仅靠计算机本身还没有很大的能力来确定可以单线程运行的进程可以并行运行。请注意,此时他们可能具有这种能力,因此不需要计算机程序员,因为可以执行此操作的计算机系统也可以编写自己的代码1 .。

考虑以下简单的数学表达式:

(4 + 2) * 17 / (3 + 6)

有可能并行计算,但是在逻辑上是有限的。我会说没有多于两个线程是没有意义的,即使那样,它基本上只会是一个:

#1 a) 4 + 2 b) 6 * 17 c) 102 / 9
#2 a) 3 + 6

线程#2通过计算3 + 6 = 9进行了贡献,线程#1在步骤C中使用了该线程,并节省了一步。但是,就并行性而言,这将是有益的。尽管线程2 可以计算17/9,而线程1 却可以计算6 * 17,但是这样做毫无意义,因为您现在有两个无法重新组合的通往同一目标的不同路径。即,#2可以继续工作:

b) 17 / 9 c) 1.888 * 6

并且最终得到与线程#1(11.333)相同的结果,但是他们在步骤A之后没有互相帮助,因此让他们两个追求这个目标是浪费时间。

(请注意,该示例不是一个字面的示例;它只是为了说明一种逻辑原理。在用户代码中线程执行任务的规模要大得多,但是在多线程编程中,您不需要真正的课程即可掌握这里的想法。)

利用多个处理器需要编写相应的代码。您不能简单地说:“哦,使用所有4个内核,并更快地完成!”。那不会发生的。从逻辑上讲,很多(或大多数)问题和任务涉及无法并行发生的步骤,这些步骤必须按顺序进行。


1.但请参阅下面的费利克斯·唐贝克(Felix Dombek)的评论;我不是AI方面的专家。值得一提的是,按照彼得·科德(Peter Corde)的评论,操作系统可以利用现代指令集和处理器以并行方式优化非常细粒度的事物,并且硬件管道也可以做到这一点,尽管不能跨内核(单个核心执行的事情不止一件事,即在最终执行之前的不同时间对指令流进行操作。我试图在此处坚持用户线程的主题,因为我认为这或多或少是您所要获得的。


4
我已经写了很多并行的数字代码,这对于细节有些误导。您不会在这样的单个算术运算级别上并行化。(如果我们扩展到Raspberry Pi之外,无论如何,有些编译器和处理器已经可以并行化其中的一些线程,甚至在线程结构之外。)您可以将整个任务并行化为更大的块。

4
@Brick“您不会在这样的单个算术运算级别上并行化。” ->当然可以,但是我会更清楚地表明这是一个类比,而不是一nuts不漏的多线程编程课程。
goldilocks

4
您以示例为例的计算中的并行性已被本地化,以至于它将在计算该程序的程序中创建指令级并行性,而无序执行的CPU 可以自行利用该并行性。
彼得·科德斯

2
RPi3使用顺序为2的超标量en.wikipedia.org/wiki/ARM_Cortex-A53,因此,通过谨慎的指令调度,编译器仍然可以通过将两条add指令彼此相邻放置来利用ILP,以便它们可以在同一条指令中运行时钟周期。如您所指出的,下面的乘除法余数将通过数据依赖关系进行序列化。
彼得·科德斯

1
确定可并行化部分不一定需要强大的AI。从“一般”的意义上讲,它可能;但是很容易想到计算机可以使用某种启发式方法,这种方法在许多实际情况下通常都有效。就像,计算机并不能证明费马的最后定理,但是肯定有定理证明程序。请注意,用于编程语言的现代编译器已经在优化步骤中进行了大量代码重新排列,这涉及对可并行部分的推理。
Felix Dombek

7

否适用于python。

其他人建议您研究线程化,这对大多数语言来说都是有效的答案,但他们没有考虑到您使用的是python。

python GIL不允许您有效利用多个内核。


4
GIL使使用所有4个内核的难度稍高一些。它绝不会使它成为不可能,甚至没有那么具有挑战性。
假名称

5

使用多个内核需要将线程级并行性显式公开给OS,这通常需要程序员编写多线程程序。(或者在不同的输入上多次运行单线程程序,例如使用进行编译make -j4

不过,某些语言的编译器支持自动并行化。例如,带有OpenMP的C或C ++可以将普通for()循环编译为启动多个线程的程序。

#pragma omp parallel for
for(int i = 0; i < 1000000; ++i)
{
   A[i] = B[i] * constant + C[i];
}

但是,这仍然必须在编写或编译程序时发生。 当前的硬件和操作系统无法使用多个内核来加速单线程程序。


相关:单个线程如何在多个内核上运行?:答案:他们没有。但是还有其他种类的并行性,例如指令级并行性,单个CPU内核发现并利用该并行度运行单个线程的速度比一次执行一条指令快。

关于这个问题,我的回答将详细介绍现代CPU如何查找和利用细粒度的指令级并行性。(主要关注x86)。通过同时运行多个指令,这只是正常CPU工作方式的一部分,而无需特别启用。(通过性能计数器,您可以查看执行一个程序时CPU设法在每个时钟上运行多少条指令,或者采取其他措施。)

请注意,RPi3使用有序的ARM Cortex-A53 CPU内核。每个内核是2宽超标量(ILP允许的每个时钟2条指令),但是不能对指令重新排序以找到更多的指令级并行度并隐藏延迟。

尽管如此,CPU仍是流水线,所以飞行中的指令总数(从获取和解码一直到流水线末端的回写阶段)仍然很重要。当数据依赖性不受限制时,CPU正在处理的每个管道阶段可以有2条指令,每个时钟的吞吐量为2条指令。(这是2宽的意思。)

它不能无序执行指令,但是通过谨慎的指令排序(通常由编译器执行),它仍然可以隐藏一条指令的等待时间,该指令需要多个周期才能准备好其输出。(例如,即使加载到高速缓存中或进行乘法运算,加载都将花费多个周期,而下一个周期要准备好加法)。技巧是对asm指令进行排序,以便在产生结果的那一条与使用结果的那一条之间有多个独立的指令。

让软件(编译器)静态地调度指令要比拥有可以在内部重新排序同时保留以程序顺序运行的幻想的硬件脆弱。对于编译器而言,即使是很小的无序窗口也很难像重新排列指令那样出色地完成工作,因为缓存丢失是不可预测的,并且在编译时很难分析跨函数调用的依赖链。并且没有硬件寄存器重新命名就限制了寄存器的数量。


当您的代码运行速度比您想要的慢时,所有这些都会给您带来一点安慰。当然,Cortex-A53的引擎盖下有很多很酷的东西,而Cortex-A57的引擎盖下还有很多很酷的东西(例如每个时钟最多3条指令的无序执行),甚至更多像Skylake这样的大型x86 CPU(更不用说时钟速度的差异了)。

https://en.wikipedia.org/wiki/Classic_RISC_pipeline相比,Cortex-A53很棒,就像您在计算机体系结构课程中将要学习的原始MIPS一样,但是按照现代标准,它是相当低端的。


1
“当前的硬件和操作系统无法使用多个内核来加速单线程程序。” 并非完全正确。例如,在一个单线程Java程序中,Java可以在其他CPU内核上完成所有GC和运行时分析/编译。运行时分析很重要,因为它可以决定在运行代码路径的基础上进行一些优化,而不会花费您的“单线程”任何东西,并且可以利用从分析中学到的知识极大地加快它的运行速度。一般来说,您的观点是好的。
Bill K

@BillK公平地说,在这种情况下,“程序” java不是myapp.jar,并且肯定不是单线程的。
goldilocks

1
没错,我只是指出,根据运行时的设计方式,即使是单线程的“编写代码”也可以利用额外的内核,而无需将其明确编码为多线程应用程序。Python也可以提供更强大的运行时,但是这毫无意义。无论如何,这都不是一个大的飞跃-我认为甚至Java都仅像额外的1/2内核一样使用单线程应用程序。
Bill K

当前的硬件和操作系统无法使用多个内核来加速单线程程序。 ”之后,您将立即解释硬件如何并行执行指令。
Thomas Weller

3
@ThomasWeller是的,但是要挑剔的处理器流水线不使用多个内核;它包含在一个内核中,但是它允许在多个指令流上工作。即,它并行性的一种形式,但不是多核线程的一种形式。
goldilocks

4

这根本不是CPU的工作原理。

从目前的情况来看,假设您的CPU不会由于80摄氏度或更高的温度相关问题而受到限制,则完全可以100%使用。话虽如此,您(通常)不想看到CPU固定在100%。如果您的CPU利用率通常为100%,则处理器可能要处理的过多。这将导致结结和普遍不愉快的用户体验。

与更实际的东西进行比较,您的CPU利用率很像汽车。这辆车可能能够以每小时100英里的速度行驶,但是您的车速表很有可能会在该速度下读取一些东西。在城里时,您可能永远无法达到每小时25英里的速度。但是这并不能改变汽车可以以每小时100英里的速度行驶。您只是没有足够努力地推动加速器。

如果您只是简单地使RPi做更多的事情(将更多的推子推到加速器上),您将看到CPU利用率上升。例如,yes在终端窗口中运行命令时请注意CPU的使用情况(请记住,这将ctrl+c结束终端命令)。这将使您的CPU增加25%,因为它将使您的四个CPU内核之一最大化。


5
我认为这个答案会误导您说您通常不希望CPU以100%的利用率运行。在许多数字密集型应用程序中,您绝对希望100%的利用率,因为您已经将一台(或多台)机器专用于计算。为了获得真正的超级计算机时间,您通常必须证明您的代码已被充分优化以执行此操作,否则它们将浪费您的资源。如果您拥有Pi群集,显然您将无法获得超级计算机的性能,但这可能对最大化使用而不是更少变得更加关键!

3
我有点同意Brick的意思,这似乎暗示着,如果处理器的使用率为25%,那是因为它是为了节省燃油或遵守速度限制;)或礼貌而不是浪费资源。您可能需要使它更清楚一点,通常是因为无论什么时候任务都在等待I / O。可以一直运行在一个核心上的事物将会。(理想情况下)阻止时间变化的原因是时间片-但实际上,堵塞一台小型单核计算机仍然很容易。
goldilocks

100%CPU使用率通常不会导致不良UX。即使大多数程序不受CPU限制,但受其他因素限制,即使1000%也足够好。由于极端的CPU负载而变慢的唯一程序是一直在实际使用CPU的程序。
Oskar Skog's

4

其他答案确实提供了很好的细节,但似乎并没有专门解决您的问题。

  1. 是的,如果程序(和操作系统)被编程为考虑多个核。(“线程化”是此处编程的术语)
  2. 机器使用每个核心所需的核心数量就可以完成任务。因此无需更改任何内容。
  3. 可以设置最大使用量限制,但无需正常使用。在这里看看答案:-https : //unix.stackexchange.com/questions/151883/limiting-processes-to-not-exceed-more-than-10-of-cpu-usage

注意:

如果您想提高pi的整体性能,则可能需要研究Overclocking。这样可以使CPU以更快的速度运行。缺点是发热量增加,处理器寿命降低以及功耗增加。


2

如果可能的话,我将参数化脚本并在单独的Python进程中执行它们。例如:

cat parameters.txt | xargs -n1 -P4 python run.py

另一个选择是已经提到的多处理库,该库使您可以分叉并加入python进程。但这还要求您具有要为其运行计算的参数列表(例如文件名)。


第一部分:是的,假设眼前的问题令人尴尬地平行的
彼得·莫滕森

没错,我只熟悉多处理的处理池,map但显然它也有许多非常复杂的共享内存构造。
NikoNyrh


0

如果要测试您的RPI。您可以stress此处的,然后可以了解如何使用CPU htop。这很有用,因为您可以查看电源是否足够,如果不够,则RPI会尝试使用过多的电流(安培),然后将其关闭。

另一方面,如果要使用python脚本,则应该joblib在并行化进程时看到哪个效果很好,因此将使用所需的处理器数量。


0

尽管所有这些答案在不同方面都是正确的,但确实操作系统将自动使用不同的内核来分散负载。您可以通过一个简单的python程序看到它(temp.py说)

while True:
  x = 1.0

从RPi桌面打开一个终端,然后键入$ top它将显示处理器的工作情况。然后打开另一个终端,python3 temp.py您将看到一个python3作业增加了100%的处理器时间。然后打开另一个终端并重复该过程,看看如何将其提升到400%。因此,在@Shadow注释的一级上,它是如此简单,并且它是默认设置。但是,正如其他人所解释的那样,设计可以使用并行处理的程序并非易事。


0

答案是肯定的!您只需编写程序即可识别它们并使用它们。这样做的程序可以使用内核。我用Java编写了代码,因此可以。

来自Python开发人员的以上答案对此答案的概念非常有限,因此可能会非常令人困惑,但答案是“是”,只有“是”!


你能详细说明一下吗?
SDsolar

0

由于OP在他的问题中未指定python,因此我想建议两种较新的语言,它们在Raspberry Pi上可以正常工作,并且具有使用并发的非常简单的方法。

我目前最喜欢的是Rust语言。我已经在Pi上编写和编译了程序。Rust很好,因为它可以防止多种类型的指针和竞争条件错误,这使得编写并发代码既容易又安全。Rust本来是一种系统编程语言,但它几乎可以完成C可以做的任何事情。

另一种这样的语言是Go(也称为Golang,以使其更易于搜索)。Go是由Google团队创建的,是一种相当成熟的语言。在Go中制作协程很容易,他们称之为“ Go例程”。

这两种语言都可以在Raspberry Pi甚至Pi Zero上编译代码。但是,它们都可以从速度更快的计算机进行交叉编译,这对于大型程序而言是不错的选择。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.