我们将用 Raspberry Pi 开始我们探索超级计算和科学编程科学领域的激动人心的旅程。但是对于我们开始这个旅程,我们必须熟悉单板计算机和 Raspberry Pi 的基础知识。在这一章中,我们将学习单板计算机的定义、历史和原理。我们首先将它与普通计算机进行比较。然后,我们将继续讨论有史以来最受欢迎和最畅销的单板计算机 Raspberry Pi。到本章结束时,读者将有足够的知识来独立设置自己的树莓派。本章旨在让读者熟悉单板计算机的基本概念和 Raspberry Pi 的设置。
单板计算机(在整本书中,从下文开始将被称为 SBCs)是一个围绕单个印刷电路板构建的全功能计算机系统。SBC 具有微处理器、存储器、输入/输出和最小功能计算机所需的其它特征。与台式个人电脑(PC)不同,大多数 SBC 没有用于外围功能或扩展的扩展槽。因为所有组件,例如处理器、RAM、GPU 等。集成在一个 PCB 上,我们无法升级 SBC。
很少有单板机是为了系统扩展而插入底板的。SBC 有许多种类、大小、形状、外形和功能。由于电子和半导体技术的进步,大多数单板机的价格非常低。SBCs 最重要的特征之一是成本效益。每个价格约为 50 美元,我们手中有一个开发工具,适用于新的应用程序、黑客攻击、调试、测试、硬件开发和自动化系统。
单板机通常以下列形式制造:
下面是 SBCs 和普通电脑的区别表(表 1-1 )。
表 1-1。
Differences Between SBCs and Regular Computers
所有 SBC 主要是 SOC。片上系统或片上系统(SOC 或 SoC)是一种集成电路(IC ),它将计算机的所有组件都集成在一个芯片上。SOC 在移动电子设备中非常常见,因为它们具有低功耗和多功能性。SOC 广泛应用于手机、SBC 和嵌入式硬件中。SoC 拥有其运行所需的所有硬件和软件。
使用 SoC 的最大优势是它的尺寸。如果我们使用中央处理器,就很难制造出一台紧凑的计算机,这仅仅是因为我们需要在一块板上排列大量的单个芯片和其他组件。然而,使用 SOC,我们可以在智能手机和平板电脑中放置完整的特定应用计算系统,并且仍然有足够的空间来放置电池、天线和远程电话和数据通信所需的其他附件。
由于非常高的集成度和紧凑的尺寸,SoC 比常规 CPU 消耗的功率要少得多。对于移动和便携式系统,这是 SOC 的一大优势。此外,通过消除计算机电路板上的冗余 IC 来减少芯片数量,可实现紧凑的电路板尺寸。
Dyna-Micro 是第一款真正的 SBC。它基于英特尔 C8080A,并使用英特尔的第一个 EPROM,C1702A。dyna-micro 于 1976 年由康涅狄格州德比的 E&L Instruments 公司更名为 MMD 1 号(Mini-Micro Designer 1)。它作为微型计算机的主要例子而出名。在计算的早期,单板机非常流行,因为许多家用计算机实际上都是单板机。然而,随着个人电脑的兴起,单板机的受欢迎程度下降了。自 2010 年以来,由于 SBC 的生产成本较低,SBC 再次受到欢迎。
除了 MMD-1,以下是一些受欢迎的历史 SBC:
基于制造商和设计师,SBC 分为系列、型号和代。一些受欢迎的 SBC 系列有
Raspberry Pi 是由 Raspberry Pi 基金会在英国开发的一系列信用卡大小的 SBC。树莓派基金会成立于 2009 年。开发 Raspberry Pi 的目的是通过提供一个低成本的计算平台来促进学校和发展中国家的基础计算机科学教学。
树莓派基金会的树莓派于 2012 年发布。这是一次巨大的成功,两年内售出了 200 多万台。随后,树莓派基金会修订了树莓派的版本。他们还发布了 Pi 的其他配件。
我已经在 Raspberry Pi 模型 B+、2B 和 3B 上编写、执行和测试了本书的所有代码示例。树莓派 3 型号 B(也称为 3B)是树莓派 的最新型号。让我们看看树莓派 3 Model B 的规格(参考表 1-2 )。
表 1-2。
Specifications of Raspberry Pi 3 Model B
下面(图 1-1 )是树莓派 3 Model B 的俯视图。
图 1-1。
Raspberry Pi 3 Model B top view
下面(图 1-2 )是树莓派 3 Model B 的仰视图。
图 1-2。
Raspberry Pi 3 Model B bottom view
下表(表 1-3 )列出了树莓派 2 Model B 的规格。
表 1-3。
Specifications of Raspberry Pi 2 Model B
下表(表 1-4 )列出了树莓派 1Model B+的规格。
表 1-4。
Specifications of Raspberry Pi 1 Model B+
我们必须先设置树莓派,然后才能开始使用它进行探索和冒险。下面我们来详细看看如何设置。正如我前面提到的,我使用 Raspberry Pi 3 Model B 进行设置。树莓派 2 型号 B 和树莓派 1 型号 B+的设置过程完全相同。让我们来看看安装所需的硬件材料清单。
安装需要下列硬件。
我们需要使用树莓派 3 模型 B 或树莓派 2 模型 B 或树莓派 1 模型 B+进行设置。
需要一台带互联网连接的 Windows 电脑或笔记本电脑。我们需要使用计算机为 Pi 准备一个带有 Raspbian 操作系统映像的 microSD 卡。
需要一个标准 USB 键盘和一个 USB 鼠标。
需要一个存储容量至少为 8 GB 的 microSD 卡(例如参见图 1-3 )。我们将使用该卡作为 Pi 的二级存储。建议使用等级 10 的卡,因为等级 10 的数据传输速度非常快。安全起见,我建议至少使用 8 GB 的卡。大多数情况下,选择 16 GB 的卡就足够了。
图 1-3。
所有 Raspberry Pi 型号都需要 5V 微型 USB 电源装置(PSU)。树莓派 3 型 PSU 的推荐电流容量为 2.5 安培。对于所有其他型号 2 安培 PSU 是绰绰有余。
我们还需要一个读卡器。许多笔记本电脑都有内置的 SD 读卡器。
如果笔记本电脑或读卡器只能使用 SD 卡,那么我们需要一个额外的 microSD-to-SD 卡适配器。下图(图 1-4 )显示了一个适配器。
图 1-4。
我们需要一个 HDMI 显示器或 VGA 显示器。
对于 HDMI 显示器,我们需要一根 HDMI 电缆(参见图 1-5 )。它通常与 HDMI 显示器一起包装。
图 1-5。
对于 VGA 显示器,我们需要一根 VGA 电缆(参见图 1-6 )。这通常也与 VGA 显示器一起包装。
图 1-6。
如果我们使用 VGA 显示器,我们将需要一个 HDMI-VGA 适配器,因为 Raspberry Pi 只有一个 HDMI 端口用于视频输出(图 1-7 )。
图 1-7。
手动准备用于 Pi 的 microSD 卡是将操作系统安装到单板计算机的 microSD 卡中的最佳方式。许多用户(包括我)更喜欢它,因为它允许在用于启动之前手动修改 microSD 卡的内容(如果需要)。准备 microSD 的另一种方法是使用 NOOBS(新的开箱即用软件),我在本书中没有使用过。
让我们下载所需的软件。
将 microSD 卡插入读卡器。如果您的电脑或笔记本电脑有内置读卡器,请将其插入。如果读卡器或您的电脑只有一个 SD 卡插槽,您可能必须使用 microSD-to-SD 卡适配器。
打开 Win32DiskImager。选择图像文件的位置,然后单击写入按钮。见下图 1-8 。
图 1-8。
Win32 Disk Imager
如果您看到以下警告消息(图 1-9 ,则切换读卡器或 SD 卡适配器(或两者)的写保护槽。然后再次点按“写入”按钮。
图 1-9。
Write protection error message
将显示以下(图 1-10 )警告信息。单击“是”按钮继续。
图 1-10。
Overwrite warning message
一旦操作系统映像被写入 SD 卡,将显示以下消息(图 1-11 )。单击确定按钮。
图 1-11。
Write successful message
Raspbian 操作系统已经刷新到 microSD 卡。
Note
如果你打算使用 VGA 显示器,这一步是必须的。如果您使用的是 HDMI 显示器,请跳过这一步。
将 microSD 卡再次插入读卡器,并在 Windows 资源管理器中浏览。在 Windows 资源管理器中,它将被表示为标记为boot的可移动介质驱动器。
完成上述更改后,保存文件。
microSD 卡现在已准备好用于 Pi 和 VGA 监视器。
让我们用准备好的 microSD 卡启动 Pi。其步骤如下:
此时,树莓派将启动。
对于所有配备单核处理器的 Raspberry Pi 机型,开机画面如下(图 1-12 )。
图 1-12。
Single-core CPU RPi model boot screen
树莓派所有搭载四核处理器的机型,开机画面都会如下图(图 1-13 )。
图 1-13。
Quad-core CPU RPi Model boot screen
一旦 Pi 启动,监视器显示如下的桌面(图 1-14 )。
图 1-14。
Raspbian Desktop (as of February 2017)
我们现在需要配置 Pi 以备将来使用。就这么办吧。
在桌面上,有一个任务栏。在任务栏中,我们发现了下面的图标(图 1-15 )。
图 1-15。
LXTerminal icon
点击图标,LXTerminal 窗口(图 1-16 )将会打开。
图 1-16。
LXTerminal Window
该终端是一个独立于桌面的基于 VTE 的 LXDE 终端模拟器,没有任何不必要的依赖。在提示符下键入sudoraspi-config并按回车键。raspi-config是树莓派 的配置工具。
导航至引导选项(在图 1-17 中突出显示)。
图 1-17。
raspi-config with boot options highlighted
图 1-18。
Desktop Autologin highlighted
在国际化选项中,更改时区和 Wi-Fi 国家(参见图 1-19 )。把键盘布局改成美国。
图 1-19。
raspi-config internationalization options
完成后,返回主屏幕并选择完成,如下图所示(图 1-20 )。
图 1-20。
Finish
它将要求重启(图 1-21 )。选择是。
图 1-21。
Reboot Prompt
它将重新启动 Pi。
我们的工作还没有完成。我们需要学习如何将 Pi 连接到互联网,以及如何更新它。
操作系统是使计算机工作的一组基本程序和实用程序。它是用户和计算机之间的接口。Raspbian 是一个基于流行的 Linux 发行版 Debian 的免费操作系统。Raspbian 针对 SBCs 的 Raspberry Pi 系列进行了优化。它甚至被移植到其他类似的单板机,如香蕉亲。
Raspberry Pi 没有常规的 BIOS。BIOS(基本输入/输出系统)是计算机的微处理器用来启动计算机系统并在计算机通电后将操作系统加载到内存中的程序。它还管理计算机操作系统和连接的外围设备(如硬盘、视频适配器、键盘、鼠标和打印机)之间的数据流。
在 Raspberry Pi 上,我们可以在 LXTerminal 中使用以下命令编辑该文件:
Note
要将 Pi 连接到任何网络,我们必须编辑/etc/network/interfaces文件。如果 Pi 连接的网络连接到 Internet,则 Pi 可以访问 Internet。
树莓派 3 型号 B 内置 WiFi。对于所有其他型号的 Pi,我们需要使用 USB WiFi 适配器。
将 USB WiFi 适配器连接到 Pi 后,使用以下命令备份/ etc/network/interfaces文件:
原始的/etc/network/interfaces文件以这种方式是安全的,并且如果出现问题可以恢复。
现在创建一个新的/etc/network/interfaces文件。
在其中键入以下行(列表 1-1 ):
在上面的文件中(列表 1-1 )用你的 WiFi 网络的 ssid 替换"ASHWIN",用你的 WiFi 网络的密码替换"internet"。通过按 CTRL+X 和 y 保存文件。
运行以下命令重新启动网络服务:
如果您正确执行了这些步骤,Pi 应该连接到 WiFi 网络和互联网(前提是 WiFi 网络已连接到互联网)。
要验证与互联网的连接,请使用以下命令:
它应该显示类似下面的输出。
像上面这样的输出意味着 Pi 连接到了互联网。
要查找 Pi 的 IP 地址,请使用 ifconfig 命令。在其输出中,检查wlan0部分。具体如下:
在上面的输出中,192.168.0.122是 Pi 的 IP 地址。由于 IP 地址是使用 DHCP 协议分配的,因此根据 WiFi 网络设置的不同,IP 地址也会有所不同。
我们还可以将 Pi 连接到局域网。根据 LAN 交换机的设置,我们可以静态或动态地为 Pi 分配 IP 地址。
如果局域网静态分配 IP 地址,则按如下方式配置/etc/network/interfaces(列表 1-2 ):
在上面的文件中,参数address、gateway、netmask、network和broadcast基于局域网的配置。请查看局域网交换机或路由器的手册。如果您在组织中工作,请向网络管理员咨询这些参数。
这是一个简单的问题。如果局域网具有 DHCP 功能,则按如下方式配置/etc/network/interfaces(列表 1-3 ):
这将配置 Pi 通过 DHCP 自动获取 IP 地址。
Note
为此,Pi 必须连接到互联网。
固件是嵌入电子设备 ROM 芯片的软件。它提供对设备的控制和监控。要更新 Pi 的固件,运行sudo rpi-update。它将更新固件。
我们将为此使用 APT。APT 代表高级打包工具。这是一个处理 Debian 和其他 Debian 衍生软件的安装和删除的程序。APT 通过自动获取、配置和安装软件包,简化了在 Debian 系统上管理软件的过程。我们也需要一个互联网连接。
首先,通过在 LXTerminal 中输入以下命令来更新系统的程序包列表:
apt-get update从各自的远程存储库下载软件包列表,并在本地计算机上更新它们,以获取可用于安装和更新的最新版本软件包及其依赖项的信息。它应该在运行install或upgrade命令之前运行。
接下来,使用以下命令将所有已安装的软件包升级到最新版本:
apt-get dist-upgrade获取机器上标记为要在本地机器上升级的软件包的新版本。它还检测和安装依赖关系。它可能会删除过时的软件包。
Note
在raspi-config中,转到高级选项(参见图 1-22 )并选择更新。
图 1-22。
Updating raspi-config
我们可以用sudo shutdown -h now安全关闭 Pi。
我们可以用sudo reboot -h now重启 Pi。
在本章中,我们介绍了 SBCs 的概念和原理。我们也开始使用 SBC 的一个流行系列,Raspberry Pi。现在我们可以满怀信心地进行进一步的探索。在下一章,我们将学习一些重要的 Linux 命令以及如何远程连接到 Pi。
在上一章中,我们学习了单板计算机的基础知识以及如何设置 Pi。我们还学会了将 Pi 连接到互联网。我希望所有读者现在对这些基础知识都很熟悉了。完成这些后,我们将会更深入地挖掘一些基础知识。在这一章中,我们将学习一些对我们有用的重要的 Linux 命令。我们还将研究如何远程连接到 Pi。
在这一节中,我们将研究几个重要的 Linux 命令,这些命令将有助于我们理解将用于超级计算和并行编程的硬件环境(Pi)。
我们可以使用 man 命令或- help 选项来获取有关命令的更多信息。例如,如果我们想更多地了解 cat 命令的用法,那么我们可以发出命令 man cat 或 cat - help。
ifconfig 用于检查网络状态。我们可以使用 ifconfig eth0 或 ifconfig wlan0 分别检查 WiFi 或以太网的状态。
我们可以使用 iwconfig 来检查无线网络状态。其输出如下:
iwlist wlan0 扫描显示所有可用无线网络的列表。
ping 测试两台设备之间的网络连通性。我们已经在第一章中看到了它检查互联网连接的用法。
这些命令帮助我们更多地了解 Pi 上系统和硬件的状态。
我们可以使用 cat /proc/cpuinfo 来查看关于 CPU 的信息。
要检查其他细节(即 CPU 的运行速度),可以使用 lscpu 命令。lscpu 的输出如下:
我们可以使用 cat /proc/meminfo 来获得关于内存的细节。我们还可以使用 free 命令来查看有多少可用内存,如下所示:
uname -a 提供关于当前系统的信息如下:
要识别 Linux 版本,请运行命令 cat /proc/version。
cat /proc/partitions 提供了分区块分配信息。
hostname -I 显示了 IP 地址。
lsusb 显示连接到 Pi 的所有 usb 设备的列表。
vcgencmd measure_temp 显示 CPU 的温度。
vcgencmd get _ mem arm & & vcgencmd get _ mem gpu 显示 CPU 和 GPU 之间的内存分割。
要远程连接到 Pi,我们需要从 raspi- config 启用 SSH 服务器。打开 LXTerminal 并运行命令 sudo raspi-config。
在 raspi-config 的主菜单中选择高级选项。在高级选项屏幕中,选择 A4 SSH,将出现以下屏幕(图 2-1 )。
图 2-1。
Enabling the SSH server
选择是,将显示以下信息(图 2-2 )。
图 2-2。
SSH server enable confirmation
按回车键。从 raspi-config 的主菜单中选择 Finish,并在提示重新启动时选择 Yes。一旦 Pi 重启,我们就可以远程访问了。
如果我们用来连接 Raspberry Pi 的计算机也在同一个网络中(无论是物理上还是通过 VPN),远程连接到 Pi 是可能的。为此,我们必须使用各种工具和实用程序。在本章中,我们将学习远程连接到 Pi。我们还将学习如何在 Pi 之间来回传输文件。当我们想在无头模式下使用 Pi 时,这一点很重要(“无头”只是指我们使用的 Pi 没有附加可视显示)。在我们没有显示器或者由于资源/空间限制而不想备用显示器的情况下,这很有用。例如,当我们创建一个 Pi 集群时,我们不能为集群中的每个 Pi 留出一个显示器。在这种情况下,无头模式非常有用。在本章的这一部分,我们将探索远程使用 Pi 的多种方法。
我们计划连接到 Pi 的计算机必须在同一个网络中,这一点很重要。在其他计算机和 Pi 之间不应该有任何代理和防火墙限制。这种设置的最佳示例是 Pi 和另一台计算机连接在同一个路由器/网络交换机下。要检查连通性,我们可以使用 ping 实用程序。
我们可以在任何装有 Linux 发行版或 macOS 的计算机上使用相同的 ping 命令,只要它们与 Pi 在同一个网络中。
PuTTY 是开源软件,有源代码,由一个志愿者团队开发和支持。
图 2-3。
PuTTY desktop shortcut
双击 putty 快捷方式,将会打开 PuTTY(图 2-4 )窗口。
图 2-4。
PuTTY Window
在主机名(或 IP 地址)文本框中键入 IP 地址或主机名。确保选择 SSH 作为连接类型。为了将来使用,你可能想要保存设置(我通常这样做)。现在,单击打开按钮。它会打开一个终端风格的窗口。它会要求你输入用户名和密码,分别是 pi 和 raspberry。首次登录时,显示如下(图 2-5 )消息对话框。单击是。
图 2-5。
PuTTY security alert
图 2-6。
PuTTY remote connection window
我们现在可以远程使用 Pi 的命令提示符了。
树莓派 桌面是 LXDE(轻量级 X11 桌面环境)。我们可以使用 RDP(远程桌面协议)客户端从 Windows 计算机远程访问它。为此,我们需要在 Pi 上安装 xrdp。通过运行 sudo apt-get install xrdp 来安装它。安装后重新启动 Pi。
我们现在必须使用 Windows 远程桌面客户端来连接到 Pi。可以使用 Windows 中的搜索选项找到客户端。单击 Remote Desktop 客户端图标将其打开。
在下面的对话框中(图 2-7 ,点击选项将其展开。
图 2-7。
Remote Desktop Connection
它展开并显示各种选项(图 2-8 )。输入 pi 的 IP 地址和 Pi 作为用户名。单击复选框和保存按钮,保存相同的配置供将来使用。
图 2-8。
Remote Desktop Connection options
图 2-9。
First time remote login
它将显示树莓派桌面。由于 Pi 通过网络传输桌面,操作速度会稍慢。然而,它工作得很好。
这就是我们如何使用 Windows 电脑/笔记本电脑访问 Pi 的桌面。然而,我们所学的方法都不允许我们在 Windows 计算机和 Pi 之间传输文件。我们将在本章的下一节学习如何去做。
图 2-10。
WinSCP window
在主机名文本框中输入 Pi 的 IP 地址。另外,输入 pi 作为用户名,输入 raspberry 作为密码。
我们还可以保存设置以备将来使用。保存会话(图 2-11 )对话框如下。
图 2-11。
Save session
图 2-12。
First time login dialog box
图 2-13。
WinSCP file transfer window
本地 Windows 计算机的文件系统在左侧面板中,而 Raspberry Pi 的 Pi 用户的主目录即/home/pi 在右侧面板中。我们现在可以在两台计算机之间传输文件了。
让我们学习使用 Linux 计算机或 macOS 连接到 Pi。
SSH 内置于 Linux 发行版和 macOS 中。我们可以使用 SSH 从 Linux 计算机(也可能是另一个 Raspberry Pi)或 Mac 终端连接到 Pi,而无需安装额外的软件。
在 Linux 计算机或 Mac 中打开终端,并键入以下命令:
192.168.0.2 是我 Pi 的 IP 地址。用您的 Pi 的 IP 地址替换它。一旦我们按下回车键,它将显示一个安全/真实性警告提示。键入 yes 继续。此警告仅在我们第一次连接时显示。
现在它会提示输入密码。输入 pi 用户的默认密码 raspberry。我们将看到 Raspberry Pi 提示符,它与 Raspberry Pi 上的提示符完全相同。
我们还可以通过 ssh 转发 X11 会话,以允许使用图形应用程序,方法是在 SSH 命令中使用-Y 标志,如下所示:
让我们远程访问像 scratch 这样的图形程序。运行以下命令,
它将在 Linux 计算机或 Mac 上的新窗口中启动 Pi 程序scratch的新 X11 会话。&使命令在后台运行。
在 Windows 中,我们使用 WinSCP 在 Windows 计算机和 Pi 之间进行文件传输。同样,我们可以在 Linux 计算机/Mac 和 Pi 之间传输文件。为此,我们需要使用 scp 实用程序。它内置于所有的 Linux 发行版和 macOS 中。
要将文件从 Pi 复制到 Linux 计算机或 Mac 上,我们必须在 Linux 计算机或 Mac 上的终端中运行以下命令:
同样,我们可能希望将文件从 Linux 计算机或 Mac 计算机复制到 Pi。为此,在 Linux 计算机或 Mac 的终端中运行以下命令:
EXERCISE
完成下面的练习,更好地理解本章。
在本章中,我们探讨了远程连接到 Pi 的各种方法。我们还学习了如何在 Pi 和其他使用 Linux、Windows 和 Mac 作为操作系统的计算机之间传输文件。
在上一章中,我们学习了重要的 Linux 命令,以及如何从其他计算机远程连接到 Raspberry Pi。我们还学习了如何在 Raspberry Pi 之间传输文件。
在这一章中,我们将开始学习 Python。
让我们从 Python 的介绍开始这一章。我个人觉得 Python 很神奇,已经被它迷住了。Python 是一种简单而强大的编程语言。当我们使用 Python 时,很容易关注给定问题的解决方案的实现,因为程序员不必担心编程语言的语法。Python 完美契合了 Raspberry Pi 的理念,即“为所有人编程”。这就是为什么 Python 是 Raspberry Pi 和许多其他 SBC 的首选编程平台。
Van Rossum 是 Python 编程语言的主要作者。他在指导 Python 编程语言的开发、错误修复、增强和进一步发展方面起着核心作用。他拥有 Python 终身仁慈独裁者的称号。他目前(截至 2017 年 2 月)为 Dropbox 工作,并将几乎一半的时间用于 Python 编程语言的进一步开发。
它是 20 个软件原则的集合,其中 19 个已经被文档化。这些原则如下:
下面是 Python 的一些特性,正是这些特性让它在编程社区中变得流行和受欢迎。
Python 是一种简单的极简主义语言。阅读一个好的、写得好的 Python 程序会让我们觉得好像在阅读英文文本。
由于其简单的、类似英语的语法,Python 对于初学者来说非常容易学习。这就是现在它作为第一编程语言被教授给学习编程入门和编程 101 课程的高中生和大学生的主要原因。新一代的程序员正在学习 Python 作为他们的第一门编程语言。
与其他高级编程语言不同,Python 没有提供太多混淆代码和使其不可读的措施。与用其他编程语言编写的代码相比,Python 代码类似英语的结构更容易阅读。这使得它比其他高级语言如 C 和 C++更容易理解和学习。
由于 Python 代码易于阅读、理解和学习,任何维护代码的人都可以在相当短的时间内熟悉代码库。我可以从我维护和增强大型遗留代码库的个人经验中证明这一点,这些代码库是用 bash 和 Python 2 的组合编写的。
Python 是一个开源项目。它的源代码是免费的。我们可以根据需要对它进行修改,并在应用程序中使用原始代码和修改后的代码。
在编写 Python 程序时,我们不必管理低级别的细节,如内存管理、CPU 计时和调度过程。所有这些任务都由 Python 解释器管理。我们可以直接用易于理解的类似英语的语法编写代码。
Python 解释器已经被移植到许多操作系统平台上。Python 代码也是可移植的。如果我们足够小心地避免任何依赖于系统的编码,所有的 Python 程序都可以在任何支持的平台上工作,而不需要做很多改变。
我们可以在 GNU/Linux、Windows、Android、FreeBSD、Mac OS、iOS、Solaris、OS/2、Amiga、Palm OS、QNX、VMS、AROS、AS/400、BeOS、OS/390、z/OS、psion、Acorn、PlayStation、sharp suzanrus、RISC OS、VxWorks、Windows CE 和 PocketPC 上使用 Python。
Python 是一种解释型语言。让我们理解这是什么意思。用 C、C++和 Java 等高级编程语言编写的程序首先被编译。这意味着它们首先被转换成中间格式。当我们运行程序时,这个中间格式由链接器/加载器从辅助存储器(即硬盘)加载到内存(ram)中。所以 C,C++和 Java 有独立的编译器和链接器/加载器。Python 就不是这样了。Python 直接从源代码运行程序。我们不必费心编译和链接到适当的库。这使得 Python 程序具有真正的可移植性,因为我们可以将程序从一台计算机复制到另一台计算机,只要在目标计算机上安装了必要的库,程序就可以正常运行。
Python 支持面向过程的编程以及面向对象的编程范例。
Python 支持面向对象的编程范例。所有面向对象的编程范例都是用 Python 实现的。在面向对象的编程语言中,程序是围绕结合数据和相关功能的对象构建的。Python 是一种非常简单但功能强大的面向对象编程语言。
Python 的一个特点就是我们可以从 Python 程序中调用 C 和 C++例程。如果我们希望应用程序的核心功能运行得更快,那么我们可以用 C/C++编写这部分代码,并在 Python 程序中调用它(C/C++程序通常比 Python 运行得更快)。
Python 有一个广泛的标准库,它预装在 Python 中。标准库拥有现代编程语言的所有基本特性。它提供了数据库、单元测试(我们将在本书中探讨)、正则表达式、多线程、网络编程、计算机图形、图像处理、GUI 和其他实用程序。这是 Python“包含电池”哲学的一部分。
除了标准库之外,Python 还有大量且不断增长的第三方库。这些库的列表可以在 Python 包索引中找到。
Python 通过处理错误的能力来提供健壮性。遇到的错误的完整栈跟踪是可用的,并使程序员的生活更可忍受。运行时错误被称为异常。允许处理这些错误的特性被称为异常处理机制。
Python 被用作快速原型制作工具。正如我们前面看到的,Python 的特性是它有丰富的库,并且容易学习,所以许多软件架构师越来越多地使用它作为工具,在很短的时间内将他们的想法快速原型化为工作模型。
在汇编语言和像 C 和 C++这样的编程语言中,内存管理是程序员的责任。这是手头任务之外的工作,给程序员带来了不必要的负担。在 Python 中,Python 解释器负责内存管理。这有助于程序员避开内存问题,专注于手头的任务。
Python 拥有现代编程语言所需的一切。它用于计算机视觉、超级计算、药物发现、科学计算、模拟和生物信息学等应用。全世界数百万程序员使用 Python。很多大品牌像 NASA,Google,SpaceX,思科(我在那里工作过!)将 Python 用于他们的应用程序和基础设施。
我个人认为这是 Python 最吸引人的特性。正如我们所看到的,由于 Python 是开源的,并且在全世界拥有近百万程序员的社区(可能更多,因为今天的高中生也在学习 Python),互联网上有大量的论坛来支持遇到任何障碍的程序员。我提出的与 Python 相关的问题没有一个是没有答案的。
Python 3 发布于 2008 年。Python 开发团队决定去掉 Python 语言的一些冗余特性,简化一些其他特性,纠正一些设计缺陷,并添加一些更急需的特性。
我们决定为此需要一个主要的修订版本号,并且最终发布的版本不会向后兼容。Python 2.x 和 3.x 应该并行共存,以便程序员社区有足够的时间将他们的代码和第三方库从 2.x 迁移到 3.x。在许多情况下,Python 2.x 代码不能按原样运行,因为 2.x 和 3.x 之间存在显著差异。
根据上面的列表,我们将在本书的代码示例中广泛使用 print()方法、新型类、异常和异常处理机制。
Note
根据上面的列表,我们将在本书的代码示例中频繁使用新的样式类和异常。
虽然许多 Python 专家仍在鼓吹 Python 2,但我完全不同意他们的观点。
Python 2.x is the heritage, and Python 3.x is the present and future of language.
支持 Python 2 的一个主要理由是大量的文档、书籍和第三方库。然而,大多数开发人员已经在将他们的定制库移植到 Python 3 上了。几乎所有主要的第三方库都被移植并完全支持 Python 3。就书籍和文档而言,像我这样的作者正在大量编写 Python 3。久而久之,肯定会有更多 Python 3 的文档可用。
新一代程序员正在学习 Python 3 作为他们的第一门编程语言。当他们熟悉 Python 编程的概念和哲学时,他们会逐渐了解 Python 2。
大多数组织已经开始将代码库从 Python 2 迁移到 Python 3。Python 中几乎所有的新项目都在大量使用 Python 3。
我个人认为这些是使用 Python 3 的很好的理由。
Raspbian 是 Debian 的变体。Python 2 和 Python 3 解释器预装在 Raspbian 中。可以通过在 lxterminal 中运行命令 Python 来调用 Python 2 解释器。可以通过在 lxterminal 中运行 python3 命令来调用 Python 3 解释器。我们可以通过运行 python3 -V 或 python - version 来检查 Python 3 解释器的版本。我们可以通过在 lxterminal 运行 which python3 来检查 Python 3 二进制文件的位置。
我们现在已经为 Python 编程建立了环境。让我们从 Python 的一个简单概念开始。Python 有两种模式,普通模式和交互模式。让我们详细看看这些模式。
Python 的交互模式是命令行 shell。它为每个执行的语句提供即时输出。它还将以前执行的语句的输出存储在活动内存中。当 Python 解释器执行新语句时,在评估当前输出时,会考虑之前执行的整个语句序列。我们必须在 lxterminal 中键入 python3 来调用 Python 3 解释器进入交互模式,如下所示:
我们可以在这种交互模式下直接执行 Python 语句,就像从操作系统外壳/控制台运行命令一样,如下所示:
我们不会在本书中使用交互模式。然而,这是检查小代码片段(5 到 10 行)最快的方法。我们可以使用 exit()语句退出交互模式,如下所示:
正常模式是 Python 脚本文件(。py)由 Python 解释器执行。
集成开发环境(IDE)是一个软件套件,它拥有编写和测试程序的所有基本工具。典型的 IDE 有一个编译器、一个调试器、一个代码编辑器和一个构建自动化工具。大多数编程语言都有各种 ide 让程序员的生活更美好。Python 也有许多 ide。让我们来看看 Python 的几个 ide。
IDLE 代表集成开发环境。它与 Python 安装捆绑在一起。IDLE3 是针对 Python 3 的。很受 Python 初学者的欢迎。在 lxterminal 中运行 idle3 即可。下面是一个 IDLE3 代码编辑器的截图(图 3-1 )和交互提示。
图 3-1。
IDLE3
图 3-2。
Geany
Geany 预装在最新版本的 Raspbian 中。如果您的 Raspbian 安装没有 Geany,那么可以在 lxterminal 中运行 sudo apt-get install geany 来安装它。安装后,可以在下面的截图(图 3-3 )中找到 Raspbian 菜单➤编程➤安歌 y 程序员编辑器。
图 3-3。
Raspbian Menu
图 3-4。
Set Build Commands
在此窗口中,在“执行命令”部分下,将 Python“% f”(在上图中红色框中高亮显示)更改为 python3“% f”,以将 Python 3 解释器设置为默认解释器。之后,再次运行程序,以验证一切都做得正确。
EXERCISE
为了更好地理解 Python 3 背景,请完成以下练习。
在这一章中,我们学习了 Python 的背景、历史和特性。我们还学习了 Python 2.x 和 Python 3.x 之间的重要区别。我们学习了在脚本和解释器模式下使用 Python 3。我们看了一些流行的 Python ide,并在 Pi 上为 Python 3 配置了 geany。在本书的后面部分,我们将使用 Python 3 和 mpi4py 为我们即将构建的小型超级计算机进行并行编程。在下一章,我们将学习超级计算的基础知识。
在上一章中,我们学习了 Python 编程语言的历史和哲学。
在这短短的一章中,我们将学习超级计算的概念和历史。
超级计算机是一种具有强大处理能力的特殊计算机。这是超级计算机这个术语最简单的定义。超级计算机区别于其他类型计算机的关键特征是它们巨大的处理能力。
超级计算机用于计算密集型应用。这些大多是科学应用。以下是几个例子:
控制数据公司(CDC)是超级计算机的摇篮。在这里,1964 年,西摩·克雷建造了 CDC 6600。它被称为第一台超级计算机,因为它的性能超过了同时代的所有其他计算机。它的处理速度约为 10 兆赫。1968 年,西摩·克雷建造了 CDC 7600。它的处理速度是 35 兆赫。同样,它是最快的计算机,在计算能力方面超过了所有其他计算机。
这就是超级计算机的起源。最终,克雷离开了 CDC,并成立了自己的公司来设计和开发超级计算机。克雷创造了历史上一些最成功的超级计算机,即克雷 1、克雷 X-MP、克雷 2 和克雷 Y-MP。20 世纪 90 年代见证了大规模并行超级计算机的时代,数千个处理器以各种配置相互连接。一个显著的例子是 Intel Paragon,它可能有许多 Intel i860 处理器。
超级计算机的速度是以每秒浮点运算(FLOPS)而不是 MIPS(每秒百万条指令)来衡量的。英特尔 ASCI Red 是第一台 TFLOPS (Tera FLOPS)超级计算机。2008 年,IBM Roadrunner 成为第一台速度为 PFLOPS (Peta FLOPS)的超级计算机。
超级计算领域的下一个突破将是以 Exa-FLOPS 计算处理速度的 Exascale 超级计算机。
在设计大规模并行计算系统时,通常遵循两种方法。第一种是让分布在广阔地理区域的成千上万台计算机通过互联网来解决一个特定的问题。这在像互联网这样的广域网上工作得很好。这些类型的系统被称为分布式系统。另一种方法是将数千个处理节点彼此靠近放置。这节省了大量通信时间,并且大部分处理能力用于解决计算量巨大的问题。这种方法被称为聚类。所有的超级计算机都属于这一类。
计算机集群被定义为一组松散耦合或紧密耦合在一起工作的计算机。群集中的计算机称为节点。集群中的所有节点执行完全相同类型的任务。
我们将要开发的微型超级计算机将是一个 pi 集群。所有的超级计算机都是集群,但不是所有的集群都是超级计算机。正如我们在超级计算机的定义中所了解到的,超级计算机拥有巨大的处理能力。这就是为什么每个集群都没有资格被称为超级计算机。我们将在这里构建的集群不是一台超级计算机,因为它在处理能力方面比现实世界的超级计算机逊色,但它的工作原理与现实世界的超级计算机相同。因此我们称它为小型超级计算机。自从引入大规模并行系统以来,大规模集群和功能较弱的计算机之间的界限开始变得模糊。今天,很少有自制的集群像 20 世纪 80 年代的超级计算机那样强大。根据其配置,商品集群分为以下两类。
当集群的所有节点不具有完全相同的硬件配置时,该集群被称为异构集群。在制作我的集群时,我使用了两个单位的 Pi B+,一个单位的 Pi 2,一个单位的 Pi 3,所以我的集群是一个异构集群。
与异构集群不同,Beowulf 集群中的所有节点具有完全相同的配置。我们可以用商品级硬件和 SBC(如 Raspberry Pi)制作同构集群和 Beowulf 集群。几乎所有集群都使用 Linux 的某个发行版作为其节点的操作系统。
根据您附近 Pi 模型的可用性,您可以创建异构集群或 Beowulf 集群。
让我们探讨一下超级计算领域的几个重要术语。
并行性意味着计算任务是并行执行的。这意味着这些任务是同时执行的。并行通常用于计算问题非常大的情况。大问题通常被分成更小的子问题,然后由计算机并行解决。随着多核处理器的引入,硬件本身支持并行程序的执行。运行并行程序的另一种方式是通过使用多台不同的计算机来创建并行系统。Parallel 是 serial 的反义词,意思是一个接一个地串联。并行性与另一个术语“并发性”密切相关。
让我用简单的话解释一下排比。假设有两项工作要完成,有两个人可以承担这两项工作。两个人都被分配了一项工作,他们开始各自独立地工作。这就是所谓的并行。
并发意味着许多计算任务同时进行。任务不必同时进行。在并行中,所有的任务同时执行。在并发中,它们不需要。在并发系统中,一个计算可以在不等待所有其他计算完成的情况下进行,并且可以同时进行多个计算。并发性的最好例子是操作系统中的进程调度。
让我用简单的语言解释一下并发性。假设要完成两项工作,而只有一个人可以完成所有的工作。这个人决定从第一份工作开始。他做了 30%,然后转到第二份工作。他完成了第二份工作的 40%,并切换回第一份工作。这种类型的切换会发生多次。我们可以说这两项工作都在进行中。虽然这些工作不是同时完成的,但它们正在朝着完成的方向前进。最后,两个工作都完成了。并发是顺序的反义词。
所有集群和超级计算机都使用并行性来将计算量巨大的任务分解成较小的块,然后收集结果作为最终输出。支持这种类型操作的编程范例被称为并行编程。消息传递接口(MPI)是工业界和学术界最常用的并行编程标准之一。我们将在下一章研究如何在 Python 3 的 Pi 上安装它。
在下一章中,我们将学习如何建立一个树莓派集群的节点。
在这简短的一章中,我们将开始在 Raspberry Pi 上安装必要的包和库。我们将安装 MPI4PY,这是一个用于 MPI 的 Python 库。最后,我们将安装用于节点发现的实用程序 nmap。
消息传递接口标准(MPI)是基于 MPI 论坛建议的消息传递库标准。MPI 论坛在美国和欧洲有超过 40 个参与组织。消息传递接口的目标是为消息传递定义一个可移植的、有效的、灵活的标准,它将被广泛用于编写各种各样的消息传递程序。MPI 是第一个独立于供应商的消息传递库标准。使用 MPI 标准开发消息传递程序的优点是可移植性、效率和灵活性。尽管 MPI 不是 IEEE 或 ISO 标准,但它已经成为为高性能计算(HPC)、并行计算机、集群和分布式系统等各种平台编写消息传递程序的行业标准。MPI 标准定义了库例程的语法和语义,用于用 C、C++和 Fortran 编写可移植的消息传递程序。
Note
1992 年 4 月 29-30 日,一个关于分布式内存环境中消息传递标准的研讨会在弗吉尼亚州的威廉斯堡召开。讨论了标准消息传递接口的基本特征,并成立了一个工作组来继续标准化进程。从那以后,MPI 的工作继续进行,工作组定期开会。MPI 标准草案在 1993 年 11 月的超级计算’93 会议上提出。经过一段时间的公众评议,MPI 标准发生了一些变化,1994 年 6 月发布了 MPI 1.0 版。这些会议和电子邮件讨论一起导致了 MPI 论坛的形成。来自美国和欧洲 40 个组织的大约 80 人参与了 MPI 标准化工作。到目前为止,MPI 的最新版本是 MPI-3.2,我们将使用它来构建集群。
MPI 针对具有分布式内存和连接所有节点的网络的分布式系统进行了优化,如图 5-1 所示。
图 5-1。
Distributed memory system
以下是消息传递接口的功能:
当我们开始学习如何用 MPI4PY 编码时,我们将研究 MPI 范例的更多细节。
正如我们已经看到的,MPI 不是一个库,而是开发消息传递库的标准,有几种 MPI 实现。以下是最受欢迎的实现:
MPI4PY 代表 Python 的 MPI。MPI for Python 为 Python 提供了 MPI 绑定。这允许任何 Python 程序使用多处理器配置计算机。这个包是建立在 MPI-1/2/3 规范之上的。它为 Python 中的并行编程提供了面向对象的接口。它支持任何 Python 对象的点对点(发送和接收)和集体(广播、分散和收集)通信。
图 5-2 描绘了 MPI4PY 的概况。
图 5-2。
Philosophy of MPI4PY
Python 是 HPC(高性能计算)中三种最常用的编程语言之一。另外两个是 C 和 FORTRAN。正如我们前面看到的,Python 语法很容易理解和学习。MPI 是 HPC 和并行编程的事实上的标准。自 1994 年左右(20 多年)以来,它就一直存在。MPI4PY 是一个广受好评的、干净的、高效的 Python MPI 实现。它涵盖了大部分 MPI-2 标准。这就是为什么我们要在树莓派 上使用 Python 3 配合 MPI4PY 进行并行编程。
在 Raspbian 上安装 Python 3 的 MPI4PY 非常简单。用户只需在 lxterminal 中运行以下命令:
要检查它是否已安装,请运行以下命令:
它应该输出主机名 raspberrypi。
运行以下命令启动多个进程:
输出如下所示:
我们还可以运行以下命令来检查系统上安装的 MPI 版本:
这样我们就可以安装、运行和验证 MPI4PY。
Note
nmap 是一个网络安全扫描器。我们将使用它来发现我们的 Pi 的 IP 地址。我们将在下一章使用它。现在,只需通过运行以下命令来安装 nmap:
在本章中,我们学习了通过安装 MPI4PY 为超级计算准备一个 Pi。在下一章中,我们将通过连接多个 pi 来构建一台超级计算机。
在前一章中,我们通过安装必要的库、框架和工具为超级计算准备了 Pi。在本章中,我们将学习创建一个由多个 pi 组成的网络,并使用它来并行运行各种命令。
一旦我们配置了 Pi,更新了它,并安装了必要的软件包和实用程序,我们就应该备份 microSD 卡。这是必要的,因为(上帝禁止!)如果 microSD 卡或 Pi 被损坏或丢失,那么我们可以用备份来继续我们的工作。建议始终备份一个安装并更新了 Raspbian 操作系统的 microSD 卡。此外,在安装了项目所需的必要包、工具和实用程序之后进行备份也是一个好主意,我总是遵循这个好主意。
要备份 microSD 卡,首先将其从 Pi 中取出,并将其插入 SD 读卡器。将 SD 读卡器连接到安装了 Win32DiskImager 的 Windows 计算机。打开 Win32DiskImager 并选择一个位置。为备份文件选择一个合适的名称。追加扩展名。img 或者。文件名后的 IMG。的。img 或者。IMG 扩展用于原始存储磁盘映像。见下图(图 6-1 )截图举例。
图 6-1。
Taking the microSD card backup
然后点击阅读按钮。一旦完成,将显示如下(图 6-2 )对话框。
图 6-2。
Backup completed
Raspbian OS、MPICH 和 MPI4PY 安装的更新版本的映像文件现在保存在硬盘上。我们可以使用这个图像为超级计算机的其余节点准备其他 microSD 卡。要做到这一点,我们只需要用 Win32DiskImager 把这个镜像写到其他 microSD 卡上。
使用我们在上一节中准备的操作系统映像,我们将准备超级计算机的其他节点。使用 Win32DiskImager 将此操作系统映像写入其他 microSD 卡。一旦所有的 microSD 卡都准备好了,就把它们插入 Pis。每个 Pi 应该有一个唯一的主机名。我们可以用 raspi-config 更改 Pi 的主机名。转到高级选项并选择 A2 主机名。更改主机名,如下图截图所示(图 6-3 )。
图 6-3。
Changing the hostname
主机名更改后,lxterminal 中的提示会出现在下面的截图中(图 6-4 )。
图 6-4。
The lxterminal prompt after changing the hostname
如您所见,提示符和 lxterminal 窗口标题中的主机名raspberrypi被替换为pi001。
对所有 pi 执行相同的步骤,并将它们的主机名更改为pi002、pi003等等。
这是一个有点棘手的部分。我们可以通过许多方式将 pi 连接在一起。选择取决于基础设施和可用的预算。让我们探索几个简单易行的方法。
此选项适用于受管理的网络交换机和 WiFi 路由器。访问受控交换机或 WiFi 路由器的管理控制台。登录到管理控制台后,将有选项来设置 DHCP 的地址范围。修改该范围,因为我们将向其中添加更多设备。
对于 WiFi 路由器来说,管理控制台通常是一个网页。可以通过连接到 WiFi,然后在浏览器中键入其 IP 地址来访问它。它通常以用户名和密码的形式进行验证,通常在 WiFi 路由器手册中列出。每个 WiFi 路由器都有用于有线局域网的以太网端口,如下图所示(图 6-5 )。
图 6-5。
更新/etc/network/interfaces中的网络设置,作为 IP 地址分配方案自动连接到 LAN 和 DHCP。以下是一个示例/etc/network/interfaces文件:
我们知道 Pi 3 之前的所有型号的 Pi 都需要 USB WiFi 适配器。最好的选择是如果你有一个 WiFi 路由器和许多 Pi 3s。如果 Pis 的型号早于 Pi 3,您将不得不投资购买 USB WiFi 适配器。在为相关型号的 Pi 配备 USB WiFi 适配器后,更新/etc/network/interfaces中的网络设置,以便自动连接到 WiFi。
下面是一个示例/etc/network/interfaces文件。
将ASHWIN替换为您 WiFi 网络的 ssid,将internet替换为您 WiFi 网络的密码。
这是我的首选方法。所有被管理的网络交换机和 WiFi 路由器都有一个静态 IP 地址范围。为集群中的节点选择几个地址,然后更新/etc/network/interfaces文件。使用受管网络交换机或 WiFi 路由器的 IP 地址作为网关的值。
使用低成本的非托管网络交换机可能是最便宜的选择。“未被管理”意味着它们没有管理控制台。只需用以太网电缆将 pi 连接到交换机,并按如下方式更新/etc/network/interfaces:
对于所有 pi,网络设置(除了 IP 地址)将与上述相同。IP 地址将是唯一的。此外,由于交换机不受管理,我们通过使用与网关相同的值(在上例中为 192.168.0.1)为其手动分配 IP 地址。所有 pi 的网关值必须相同。
更改网络设置后重新启动 Pis。
以下是几款低成本非托管交换机及其各自的产品页面。
不管网络类型(以太网或 WiFi)和 IP 地址分配方案(静态或动态),我们都需要知道网络中所有 pi 的 IP 地址,以便将 pi 的网络用作集群。在前一章中,我们安装了nmap实用程序。我们现在将使用它来查找网络中 pi 的 IP 地址。
将显示器、键盘和鼠标连接到pi001。我们将使用pi001作为主节点。我们将在pi001使用 lxterminal 为超级计算机运行命令和并行程序。
将所有 pi 连接到网络。我们不需要将任何显示器或 I/O 设备连接到其他 pi。
启动所有 Pis。一旦所有 pi 启动,用nmap扫描网络。
以下是扫描网络的命令:
在上面的命令中,192.168.0.*中的前三个字节对应于我的网络的 IP 地址。用网络标识符的前三个字节替换它们,并在pi001上的 lxterminal 中运行命令。
输出如下所示:
记下网络中所有覆盆子 pi 的 IP 地址。在这种情况下,IP 地址是 192.168.0.2、192.168.0.3、192.168.0.4 和 192.168.0.5。
在pi001上,通过运行以下命令导航到/home/pi:
创建一个名为myhostfile的新文件。将之前记下的所有 IP 地址添加到myhostfile中,如下所示:
现在运行以下命令:
它将显示一个带有错误的输出,并且命令hostname不会在文件myhostfile中列出的所有主机上运行。
这是因为我们试图在pi002、pi003和pi004上远程运行来自pi001的命令。我们没有这方面的认证。
ssh-keygen实用程序用于生成认证密钥。要在任意两台 Linux 计算机之间建立身份验证,请执行以下步骤:
完成后,我们可以在没有密码的情况下执行以下操作,因为在密钥交换后,不会再次提示输入密码。
我们还可以在 shell 脚本中使用ssh命令来自动化远程主机中的任务。我们使用pi001作为主节点,所以我们希望从其他节点上的pi001远程运行命令,反之亦然。我已经建立了一个包含四个节点的集群,因此用于密钥交换的主机对是(pi001,pi002)、(pi001,pi003)和(pi001,pi004)。
让我们交换钥匙。打开 lxterminal 并转到pi001的主目录。
运行ssh-keygen命令生成密钥。只要在每次提示输入时按下回车键。以下是 lxterminal 上的输出:
请注意,由于每次执行生成的密钥不同,命令提示符上显示的图像每次都会不同。
上面的执行在 Pi 的主目录中创建了一个隐藏目录.ssh。转到.ssh目录。
通过运行ls命令检查.ssh目录的内容,如下所示:
我们需要将这个pi01文件的内容添加到其他主机的authorized_keys文件中,以便在没有身份验证的情况下实现远程访问。
系统会提示我们输入pi002的密码。输入密码。
像我们在pi001上做的那样,在pi002上运行以下命令来生成公钥:
现在我们需要使用scp将pi001的公钥文件复制到pi002。
通过运行以下命令,将pi01的内容添加到authorized_keys中:
最后,使用注销命令从pi002注销。
对于pi003,我们又要按照同样的步骤。
在pi003上运行以下命令序列:
对于pi004,我们又要按照同样的步骤。
在pi004上运行以下命令序列:
在pi001中,运行以下命令序列,将pi002、pi003和pi004的公钥复制到pi001。
这就完成了集群的设置。要测试设置,在pi001上运行以下命令:
上面命令的输出应该如下所示:
恭喜你。我们已经建立了自己的小型超级计算机集群。在下一节中,我们将学习如何在一个漂亮的栈中组织我们的集群。
当我建立我的第一个集群时,我想到了创建一个定制的丙烯酸案件;然而,估计的费用超出了我的预算。我还想到通过 3D 打印为集群创建一个定制案例,但 3D 打印承包商也为此报出了一笔天文数字。所以我决定尝试一种更具成本效益的方法来组织集群中的 pi。我使用 M3 六角间隔垫片来创建一个 Pis 栈。我们需要两种类型的对峙,男性对女性和女性对女性。我们现在将使用这些来创建一个栈。重要的是,支架的长度必须至少为 25 毫米,以避免 Raspberry Pi PCBs 相互接触。
Note
在谷歌上搜索 M3 六角支架垫片。
如下图所示(图 6-6 ),取四个凸对凹支架,并将它们连接到一个 Pi 上。
图 6-6。
Attaching male-to-male standoffs to the Pi
之后,取四个凹对凹支座,将它们连接到 Pi 的底部,如下图所示(图 6-7 )。
图 6-7。
Attaching female-to-female standoffs to the cluster base
现在将第二个 Pi 连接到此处,如下图所示(图 6-8 )。
图 6-8。
Adding second Pi to the stack
最后,将剩余的两个 pi 添加到此之后,集群栈看起来如下图所示(图 6-9 )。
图 6-9。
Raspberry Pi Supercomputer stack
在本章中,我们学习了如何将几个 pi 连接在一起,构建一个超低成本的迷你超级计算机集群。我们还了解了如何在一个方便的栈中组织集群。在下一章中,我们将学习如何超频 Pi 的各种模型,以增加集群中 Pi 的计算能力,而无需额外的成本。
超频意味着配置计算机的硬件部件以比原始制造商认证的速度更快的速度运行。器件的工作速率通常用时钟频率来表示,如 MHz、GHz 等。通常超频组件的工作电压也会增加,这有助于在加速时保持组件的工作稳定性。然而,超频的缺点是,给定的半导体器件在比常规设置更高的频率和电压下工作时会产生和散发更多的热量,因此大多数超频尝试也会增加功耗和散热。为了减轻超频组件中增加的散热,我们通常必须安装散热器和冷却系统。
让我们从超频 Raspberry Pi 的基础开始。在本章中,我们将详细探讨如何安装被动散热器以及如何超频各种型号的 Raspberry Pi。
超频 Raspberry Pi 使我们能够充分利用它。然而,我们不应该在不了解风险的情况下这样做。非常重要的一点是,我们要明白我们将要面对的是什么。
这里有一些我们必须注意的超频风险:
散热器是用于吸收多余热量的装置或物质。如果您计划超频您的 Pi,那么建议在处理器、内存和图形处理器上安装散热器。
大多数散热器上都粘有不干胶。用它们在 Pi 的芯片上安装散热片。大多数人只在使用 Raspberry Pi 时使用被动散热器,因为像液体冷却和/或散热器这样的主动散热机制对 Raspberry Pi 来说太过了。
许多经销商在网上销售散热器。你可以谷歌一下关键词树莓派散热器。
以下是销售散热器的各个经销商的网站链接:
我们可以使用raspi-config工具中的超频选项对 Pi 进行超频。
下面(图 7-1 )是 Pi B 和 Pi B+中的超频选项截图。
图 7-1。
Overclock options in Pi B and Pi B+
下面(图 7-2 )是 Pi 2 中超频选项的截图。
图 7-2。
Overclock options in Pi 2
以下是 Pi B 和 Pi B+的超频选项值:
以下是 Pi 2 的超频选项值:
以下是 Pi 3 的超频选项值:
如果您的 Pi 无法启动或变得不稳定,请尝试调整这些值以获得最佳设置。
超频后,使用cat /proc/cpuinfo命令检查所有型号的处理器速度。
Note
Exercise
超频所有你打算用来构建小型超级计算机集群的 Raspberry Pis。这将在运行时方面提高个人和整体的性能。
在这一章中,我们学习了如何超频各种型号的树莓派。从下一章开始,我们将开始研究如何利用我们构建的集群的计算能力。我们将使用 MPI4PY 用 Python 3 编写代码,演示 MPI 和并行编程中的概念。
在上一章中,我们学习了如何对各种型号的 Raspberry Pi 进行超频,以增加其计算能力。在本章中,我们将学习如何用 Python 和 MPI4PY 编写并行程序。我更喜欢 Python,因为它简单,而且 Python 中的代码不那么吓人。我们将探索 MPI 概念,并用 MPI4PY 在 Python 中实现这些概念。
我们将研究和实现的 MPI 概念如下:
在本书的前面部分,我们学习了一些 MPI 概念。这一章我们再研究几个。
MPI 使用单程序多数据( SPMD )的概念。以下是 SPMD 建筑的要点:
并行程序被分解成单独的进程,称为等级。每个列都有自己的地址空间,这需要跨列划分数据。每个等级在自己的私有内存中保存一部分程序数据。等级按从 0 到 n-1 的顺序编号。下图(图 8-1 )描述了同时运行的多个队列。
图 8-1。
Multiple ranks running simeltaneously
在下一节中,我们将看到一个带有等级的基本程序。
让我们从简单的 Hello World 开始吧!用 MPI4PY 用 Python 编程。
图 8-2。
COMM_WORLD
这一章我们已经开始编码了,后面的章节有很多代码样例和练习。将代码和数据组织在单独的目录中是一个好主意。在 lxterminal 中逐一运行以下命令:
最后,在pi001上运行mpirun,如下所示:
以下是输出:
对于我们将在本章剩余部分讨论的所有其他代码示例,我们必须遵循相同的步骤。让我简单重复一遍:在chapter08目录下创建一个 Python 代码文件,将该文件复制到集群所有节点的chapter08目录下,最后使用mpirun和 Python 解释器来执行代码。
我们可以在 MPI4PY 代码中使用如下条件语句(清单 8-2 ):
在这段代码中,我们检查进程等级是 0 还是 1,然后将更多消息打印到控制台。用mpiexec运行程序如下:
上面的程序(清单 8-2 )的输出如下:
让我们编写代码(清单 8-3 )来显示 MPI 进程的等级和数量。
输出如下所示:
使用send()和receive()进行进程间的数据传输是进程间最简单的通信形式。我们可以用这个实现一对一的交流。下图(图 8-3 )清楚地解释了这一点。
图 8-3。
One-to-one communication
让我们来看看代码示例(清单 8-4 )的相同之处。
在上面的代码示例中,我们从等级为 0 的流程中发送数据。等级为 1 和 2 的进程正在接收数据。
让我们运行程序。
上面的程序(清单 8-4 )的输出如下:
到目前为止,我们已经为发送和接收数据的过程编写了条件语句。然而,在大型分布式网络中,由于进程数量的不断变化,这种类型的数据传输并不总是可能的。此外,用户可能不想手工编写条件语句。
下面的例子(清单 8-5 )展示了动态数据传输的概念。
在上面的代码(清单 8-5 )中,每个进程都从前面的进程接收数据。这种情况一直持续到结束并循环,这样第一个进程从最后一个进程接收数据。
让我们运行代码。
代码的输出如下所示:
如前所述,等级为 0 的进程(第一个进程)从等级为 3 的进程(最后一个进程)接收数据。
在前面的例子(清单 8-5 )中,我们研究了如何用 MPI 发送和接收数据。这给好奇的程序员提出了一个基本问题:我们如何在进程间交换多个数据项?我们可以将多个数据项从一个进程发送到另一个进程。然而,在接收端,我们会遇到区分不同数据项的问题。解决这个问题的方法是标记。看看下面的代码示例(清单 8-6 )。
在上面的例子中,我们将两个不同的字典shared1和shared2从等级为 0 的进程发送到等级为 1 的进程。在源端,shared1被标记为 1,shared2被标记为 2。在目的地,我们可以从与它们相关联的标签中区分不同的数据项。
用下面的命令运行上面的代码(清单 8-6 ):
输出如下所示:
数据标记使程序员能够更好地控制数据流。当多个数据在流程之间交换时,数据标记是必须的。
当数据从一个进程发送到所有其他进程时,就称为广播。考虑下面的代码(清单 8-7 ):
在上面的代码(清单 8-7 )中,在if语句中,只有当进程的等级为 0 时,我们才给数据分配一个字典。bcast()向所有进程广播数据。
运行程序。
输出如下所示:
在广播中,我们向所有进程发送相同的数据。在分散中,我们将不同的数据块发送给所有进程。例如,我们有一个包含四个项目的列表。在广播中,我们将所有这四个项目发送给所有进程,而在分散中,我们将列表中的项目发送给进程,这样每个进程都从列表中接收一个项目。下面的程序(清单 8-8 )演示了这一点。
在上面的代码(清单 8-8 )中,我们创建了一个名为 data 的列表,它的元素数量等于集群中的进程数。scatter()用于将数据分散到所有进程中。
运行代码。
以下是输出:
正如我们所看到的,每个进程从列表中接收一个项目。scatter()的限制是我们分散的数据列表的大小不能超过进程的数量。
收集数据的想法与分散相反。主进程收集由其他进程处理的所有数据。
下面的程序(列表 8-9 )演示了gather()方法。
在上面的程序(列表 8-9 )中,主进程分散数字列表。所有 MPI 进程都从列表中接收一个元素(列表的大小等于 MPI 进程的数量)。每个进程执行它接收的元素的一个操作。在我们的例子中,它是数字平方的计算。然而,在现实世界的超级计算中,操作可能相当复杂。
一旦操作完成,主进程将所有已处理的元素收集到一个新列表中。
运行代码。
输出如下所示:
在本章中,我们介绍了 Python 的 MPI4PY 库。我们用 MPI4PY 学习并实验了并行编程中各种有趣的概念。在下一章中,我们将开始使用 Python 3 中带有 Raspberry Pi 的 SciPy 栈。
在上一章中,我们学习了如何使用我们为 MPI4PY 和 Python 3 并行编程而构建的 Raspberry Pi 集群。在本章中,我们将介绍 SciPy 栈并将其安装在 Pi 上。我们还将开始使用 SymPy 进行符号编程。
SciPy(Scientific Python 的缩写)是一个用 Python 编写的科学和技术计算的开源库。
SciPy 具有用于数值运算、常微分方程解算器、快速傅立叶变换、最优化、线性代数、积分、插值、信号处理和图像处理的模块。SciPy 被全世界的科学、数学和工程社区广泛使用。还有许多其他库使用 SciPy 和 NumPy 的核心模块进行操作。OpenCV 和 SciKit 是其他主要库使用 NumPy 和/或 SciPy 的最好例子。
SciPy 栈包含以下组件:
下图(图 9-1 )总结了 Python SciPy 栈在科学计算世界中的作用。
图 9-1。
The components of the SciPy stack
在本书中,我们将学习 NymPy、SciPy 库、Matplotlib 和 SymPy。
在 Raspberry Pi 上安装 SciPy 栈的最佳方式是使用apt-get和pip。
首先,使用以下命令升级pip:
使用以下命令安装 SymPy:
SciPy 栈的其余组件可以使用apt-get实用程序方便地安装,如下所示:
这将安装所需的 SciPy 栈组件。
SymPy 网站上说:
SymPy is a Python library of symbolic mathematics. Its goal is to become a fully functional computer algebra system (CAS), while keeping the code as simple as possible so as to be easy to understand and expand. SymPy is written entirely in Python.
SymPy 是 BSD 许可的,是免费的。它完全是用 Python 编写的。它依赖于mpmath并且本质上是轻量级的,因为没有其他依赖项。
让我们从 SymPy 开始。运行以下命令创建并导航到该章节的目录:
我们将把这一章的代码保存在目录chapter09中,并将在本书的其余部分继续这一做法,即按章创建目录来组织代码。
我假设您有一些数学和微积分的基础知识,所以我在解释代码时不必解释这些基础知识。让我们看一个符号计算概念的简单例子(列表 9-1 )。
运行上面的代码(清单 9-1 )。以下是输出:
输出如下所示:
上面的代码(清单 9-2 )展示了symbols()方法可以接受一个字符串作为参数,其中的标记由空格分隔。
让我们再看一个例子(清单 9-3 ),它演示了用符号对表达式求值。
这将在表达式中用 3 代替x,并对其求值。代码(清单 9-3 )产生4作为输出。
我们可以替换多个符号如下(列表 9-4 ):
这里,我们一次替换多个符号。运行代码并检查输出。
我们可以将字符串转换成 SymPy 表达式。就像在 Python 中一样,我们可以对指数使用**操作符。下面的代码(清单 9-5 )显示了这一点:
方法将一个字符串转换成一个 SymPy 表达式。
我们还可以使用evalf()方法将表达式求值为浮点数。它的默认精度是小数点后 15 位数字;但是,我们可以将精度作为参数传递。下面(列表 9-6 显示了evalf()方法的用例示例:
SymPy 有很多打印机。在任何环境中,在命令提示符下使用init_session()方法都会启动一个交互式会话。下面是一个交互式会话的示例。我在控制台中输入的命令以粗体突出显示。
这些命令被执行:
这就是我们如何在交互式控制台中以良好的格式打印表达式。
我们可以使用simplify()方法尽可能简化数学表达式。这下涵盖了大量的表达式。以下(清单 9-8 )就是一个例子:
简化的输出如下:
SymPy 中有更多的简化方法。我们可以使用expand()来展开一个多项式表达式,如下所示(列表 9-9 )。
以下是扩展后的输出:
类似地,我们可以使用factor()方法(列表 9-10 )来寻找多项式的不可约因子。
输出如下所示:
我们甚至可以用 SymPy 来做微积分。我们可以使用diff()方法计算导数如下(列表 9-11 ):
输出是:
我们还可以找到如下表达式的高阶导数(列表 9-12 ):
输出如下所示:
我们也可以使用integrate()方法计算带有 SymPy 的积分。下面的代码(清单 9-13 )演示了这一点:
输出如下所示:
我们还可以集成如下限制(列表 9-14 ):
这里,我们对-x的指数从零到无穷大进行积分(用oo表示)。运行这个并检查输出。我们也可以计算多重极限的多重积分如下(列表 9-15 ):
运行代码(列表 9-15 )并通过手动执行集成来验证输出。
Note
在这一章中,我们从 SymPy 开始,学习了如何在 Python 中执行符号计算。在下一章,我们将从 NumPy 和 Matplotlib 开始。
在上一章中,我们学习了如何安装 SciPy 栈,以及如何在 Python 3 中使用 SymPy 进行符号计算。在这一章中,我们将被介绍到 NumPy 库,我们将学习 NumPy 的基础知识。我们还将学习使用 Matplotlib 绘制和可视化数据的基础知识。因此,让我们通过学习 NumPy 的基础知识,开始进入科学计算世界的激动人心的旅程。
努比切望 python(python 语言)
进行科学计算的基础包
其特点如下:
它有一个强大的自定义 N 维数组对象,可以高效方便地表示数据。
它拥有与其他用于科学编程的编程语言(如 C/C++和 FORTRAN)集成的工具。
它用于数学运算,如线性代数、矩阵运算、图像处理和信号处理。
到目前为止,我们一直将代码保存在.py文件中,并用 Python 3 解释器运行它。在这一章中,我们将使用一个叫做 Jupyter 的工具,这是一个基于网络的高级工具,用于在编程语言 Julia、Python 和 R .
Ju lia + pyt hon + r = Jupyter
它将 Python 3(或任何其他支持的语言,如 R 和 Julia)代码和结果保存在一种叫做笔记本的交互格式中。Jupyter 使用 Python 2 和 Python 3 的 IPython 内核。IPython 是 Python 的高级交互式 shell,具有可视化功能。Jupyter 项目是 IPython 的副产品。
Jupyter 和 IPython 具有以下特性:
可以使用以下命令轻松安装它:
这将安装 Jupyter 及其对 Raspberry Pi 的所有依赖。
Jupyter Notebook 是由 Jupyter Notebook 应用程序生成的文档,其中包含 Python 代码和丰富的文本元素,如段落、等式、图形、链接和交互式可视化。笔记本有人类可读组件和机器可读(可执行)组件。
让我们现在就开始使用 NumPy 和 Jupyter 笔记本吧。打开 lxterminal 并运行以下命令序列:
这将创建并导航到对应于当前章节chapter10的目录。
现在,这是我们的笔记本启动文件夹,让我们从这里使用以下命令启动笔记本:
它将启动 Jupyter 笔记本应用程序,并打开一个浏览器窗口(在 Raspbian 的最新版本中为 Chromium 浏览器)。
下面(图 10-1 )是 Jupyter 笔记本启动时的控制台截图:
图 10-1。
Jupyter Notebook App console
下面(图 10-2 )是 Chromium 浏览器窗口标签运行笔记本 app 的截图:
图 10-2。
Jupyter Notebook App running in Chromium
在浏览器窗口的右上方,单击 New,然后在随后的下拉菜单中选择 Python 3。见下图(图 10-3 )截图:
图 10-3。
New Python 3 notebook
它将在同一浏览器窗口中打开一个新的笔记本标签(图 10-4 )。
图 10-4。
Python 3 notebook tab
将 Jupyter 笔记本的名称改为Chapter10_Practice,如下图截图所示(图 10-5 )。
图 10-5。
Renaming the notebook
笔记本应用程序将显示一个新笔记本的实例,其名称已更新,状态为“正在运行”,如下图截图所示(图 10-6 )。
图 10-6。
Notebook running
在窗口顶部的菜单栏中,有您在任何其他 IDE 中都有的选项,例如保存、复制、粘贴和运行。
在第一个单元格中键入import numpy as np,然后单击 Run 按钮。该控件将自动创建下一个文本单元格,并将光标置于其上,如下所示(图 10-7 )。
图 10-7。
Working with Python 3 code
我们刚刚将 NumPy 导入到我们的笔记本中,因此我们不必再次导入。此外,我们也可以编辑笔记本的前一个单元格。在执行类型中,如果解释器突出了语法中的错误,我们可以通过编辑任何单元格来修复它。随着科学计算的发展,我们将对 Jupyter 有更多的了解。
NumPy 最强大的构造是 N 维数组(ndarray)。ndarray为多维同质数据提供通用容器。同构意味着ndarray中的数据项是相同的数据类型。让我们看一个 Python 中各种ndarray类型变量的例子。在笔记本中键入以下代码:
恭喜,我们刚刚创建了一维、二维和三维的ndarray对象。我们可以通过在 Jupyter notebook 中运行以下代码来验证这一点:
输出是:
NumPy 中的ndarray的索引方案与 C 语言中的相同,即第一个元素从 0 开始索引。下面一行打印了一个ndarray中第二行第三列的元素值。
我们可以按如下方式对数组进行切片:
以下是输出:
以下是对ndarray重要属性的演示:
以下是输出:
下面是正在发生的事情:
Note
具备了 NumPy 中的ndarray构造的基础,我们将在下一节开始数组创建例程。
让我们用内置数组创建例程来创建ndarrays。我们还将使用 matplotlib 来可视化创建的数组。我们将使用 matplotlib 在需要时可视化数据。这本书的最后一章是专门介绍 matplotlib 的,在这里我们会学到更多的内容。
创建ndarrays的第一种方法是ones()。您一定已经猜到了,它创建了所有值都为 1 的数组。在笔记本中运行以下语句,查看该方法的演示:
输出如下所示:
现在让我们用 matplotlib 找点乐子吧。在笔记本中运行以下示例:
在上面的例子中,我们用图形表示了ndarrays。文本结果如下:
图形输出(图 10-8 )如下:
图 10-8。
Graphical Output of arange()
图 10-9。
linspace() graph
类似地,我们有logspace()方法,它生成对数标度的数组值。下面的代码演示了:
运行笔记本中的语句,它会生成以下(图 10-10 )输出:
图 10-10。
linspace() versus logspace() graph
运行笔记本中的代码,您会看到两个示例都返回了矩阵,即使输入的格式不同。
从数组或序列构建一个矩阵。
上面的代码返回一个由所有序列组合而成的矩阵。运行笔记本中的代码,查看如下输出:
rand()和randn()方法返回带有随机数的矩阵。
我们来学习几个与线性代数(矩阵运算)相关的方法。我们有dot()方法,它计算两个数组的点积,而vdot()计算两个向量的点积。inner()计算两个数组的内积。outer()计算两个向量的外积。下面的代码示例演示了所有这些方法:
输出如下所示:
让我们把三角方法形象化。我们将使用 matplotlib 可视化sin()、cos()、tan()、sinh()和cosh()方法。下面的示例演示了这些方法的用法:
输出(图 10-11 )如下:
图 10-11。
Graph for sin(x)
以下代码示例演示了cos()的用法:
以下(图 10-12 )为输出:
图 10-12。
graph for cos(x)
让我们继续讨论双曲余弦和正弦波,如下所示:
以下(图 10-13 )是cosh()的输出:
图 10-13。
Graph of cosh(x)
下面(图 10-14 )是sinh(x)的曲线图:
图 10-14。
Graph of sinh(x)
rand()方法生成给定维数的随机矩阵。randn()方法使用从正态分布中抽取的数字生成一个矩阵。randint()在给定的界限内生成一个数,不包括这个界限。random_integers()生成包含给定限值的随机整数。下面的代码演示了上述方法的前三种:
我们可以计算 a ndarray的中值、平均值、均值、标准差和方差,如下所示:
NumPy 有一个用于基本信号处理的模块。fft模块具有fft()方法,用于计算一维离散傅立叶变换,如下所示:
输出(图 10-15 )如下:
图 10-15。
Fast Fourier Transform
fft2()和fftn()分别用于计算二维和 n 维离散傅立叶变换。试着为这些写代码。
在本章中,我们从 NumPy、matplotlib 和 Jupyter 开始,并学习了如何在 Python 中执行数值计算和基本的可视化。在下一章,我们将从 SciPy 库开始。
在上一章中,我们学习了如何使用 NumPy 进行数值计算。我们还学习了如何方便地使用 Jupyter,以及如何使用 matplotlib 进行可视化。在本章中,我们将介绍 SciPy 库。然而,我们与 NumPy 和 matplotlib 的旅程还远未结束。在本书的剩余部分,我们将学习 NumPy 和 matplotlib 的新功能。因此,让我们和 SciPy 一起踏上科学计算的激动人心的旅程。
在我们开始之前,让我们完成为本章创建一个新目录的仪式。请为本章创建一个目录chapter 11。
现在,使用以下命令启动 Jupyter 笔记本应用程序:
打开一个新笔记本,重命名为Chapter11_Practice。这个笔记本将保存本章的代码。
输出如下所示:
请注意,SciPy 常量不包括度量单位,仅包括常量的数值。这些在数值计算中非常有用。
Note
以下是输出:
我们也可以求解矩阵方程ax = b如下:
以下是输出:
我们可以如下计算矩阵的行列式:
在笔记本中运行上面的代码,自己看看结果。
我们还可以计算矩阵的范数,如下所示:
以下是结果:
我们也可以计算 QR 和 RQ 分解如下:
SciPy 有用于各种集成操作的integrate模块,所以让我们看看它的一些方法。第一个是quad()。它接受要积分的函数以及积分的极限作为参数,然后返回数值和近似误差。以下是几个例子:
以下是输出结果:
trapz()使用梯形法则沿给定轴积分:
以下是输出:
让我们看一个使用梯形法则的累积积分的例子。
以下(图 11-1 )为输出:
图 11-1。
Cumulative integration using the trapezoidal rule
这个模块有插值的方法。让我们借助 matplotlib 的图形表示来研究其中的一些。interp1d()用于一维插值,如下所示。
结果如下(图 11-2 ):
图 11-2。
1-D interpolation
interp1d()适用于y=f(x)类型的功能。类似地,interp2d()处理z=f(x, y)类型的函数。它用于二维插值。
结果如下(图 11-3 ):
图 11-3。
2-D interpolation
接下来,我们要学习splev()、splprep()和splrep()。splev()方法用于计算 B 样条或其导数。我们将把这种方法与用于表示 B 样条的splprep()和splrep(),一起使用。
splrep()用于表示一维曲线,如下所示:
结果如下(图 11-4 ):
图 11-4。
Representation of a 1-D curve
splprep()用于表示一条 N 维曲线。
下面(图 11-5 )是结果。
图 11-5。
Representation of an N-D curve
让我们从波形发生器功能开始。在∼/book/code目录下新建一个目录chapter 12。运行以下命令启动 Jupyter 笔记本应用程序:
将当前笔记本重命名为Chapter12_Practice。和前面的章节一样,在同一个笔记本中运行本章的所有代码。先导入 NumPy 和 matplotlib。
我们要研究的第一个例子是锯齿波发生器功能。
该函数接受信号的时序和宽度,并生成三角形或锯齿形连续信号。以下(图 12-1 )为输出,
图 12-1。
Sawtooth wave signal
输出如下所示:
图 12-2。
Square wave signal
脉宽调制方波正弦波可以如下所示:
输出(图 12-3 )如下:
图 12-3。
Modulated wave
窗口函数是一种数学函数,在特定区间外为零。我们现在来看看三种不同的窗口函数。第一个是汉明窗函数。我们必须将输出窗口中的点数作为参数传递给所有函数。
输出(图 12-4 )如下:
图 12-4。
Hamming window demo
汉宁窗函数如下:
输出(图 12-5 )如下:
图 12-5。
Hanning window demo
凯泽窗函数如下:
输出(图 12-6 )如下:
图 12-6。
Kaiser window demo
通过将点数和振幅作为参数传递,我们可以使用 Ricker 函数生成一个墨西哥帽小波,如下所示:
墨西哥帽小波是连续小波族中的一个特例。它用于过滤和平均光谱信号。输出如下所示:
图 12-7。
Mexican hat wavelet
我们可以用convolve()方法卷积两个 N 维数组,如下所示:
信号、窗口及其卷积如图 12-8 所示。两个信号的卷积提供了两个信号的组合以形成第三个信号。它是信号处理中一种非常重要的信号合并技术。如果信号代表图像或音频数据,我们可以基于卷积度获得改进的图像或音频。如果您还没有注意到,我们正在使用 NumPy 的repeat()方法,它把要重复的模式和重复次数作为参数。在本例中,我们生成一个样本大小为 300 的信号。
图 12-8。
Convolution
样本图像数据集可以在本书的页面上的在线下载部分获得。同样,为图书代码创建一个目录chapter 13,如下所示:
让我们看一个读取和显示图像的基本例子(清单 13-1 )。
代码(清单 13-1 将从imread()方法提供的路径中读取一个图像,并且imshow()方法将使用xlib显示它。
face()是浣熊的脸,lena()是标准测试图像,ascent()是灰度图像。
在上面的代码中(清单 13-3 ,我没有使用任何中间变量来存储图像。我通过传递给imshow()方法来直接显示它。方法imfilter()接受两个参数。
过滤器类型的允许值为'blur', 'contour', 'detail', 'edge_enhance', 'edge_enhance_more', 'emboss', 'find_edges', 'smooth', 'smooth_more', 'sharpen'。
我们可以将图像的大小调整为 50%,如下所示(清单 13-4 ):
我们也可以将图像旋转一定角度,如下所示(列表 13-5 ):
让我们从使用 NumPy 库进行图像处理的基础开始。考虑以下(列表 13-6 )代码:
上述程序(清单 13-6 )的输出如下:
这意味着图像的数据类型是 NumPy 中的ndarray。我们需要理解一些重要的ndarray属性,这将帮助我们理解它所代表的图像的重要属性。
考虑下面的代码(清单 13-7 ):
输出如下所示:
让我们来了解一下其中每一项的含义。
我们可以看到对应于单个像素的 RGB 值如下(列表 13-8 ):
在上面的代码中(清单 13-8 ,我们正在访问位于(10,10)的像素值。输出为[172 169 188]。
这些是 NumPy 用于图像处理的基础。在本章中,我们将在需要时学习更多关于 NumPy 的知识。
在上面的代码中(清单 13-9 ,我们正在导入pyplot模块。imshow()方法用于将图像添加到绘图窗口。show()方法显示绘图窗口。输出(图 13-1 )如下:
图 13-1。
pyplot imshow() demo for color image
我们还可以关闭轴(或标尺)并给图像添加一个标题,如下所示(清单 13-10 ):
由于图像是灰度图像,我们必须在imshow()方法中选择一个gray色彩映射表,以便图像的色彩空间正确显示在绘图窗口中。axis('off')用于关闭斧子。title()方法用于指定图像的标题。输出(图 13-2 )如下:
图 13-2。
Lena image with title and axis off
我们可以使用imshow()将多个图像推送到绘图窗口中的图像网格(参见清单 13-11 ),如下所示:
在imshow()之前我们已经用过subplot()的方法了。subplot()方法的前两个参数指定网格的尺寸,第三个参数指定图像在网格中的位置。网格中图像的位置编号从左上角开始。左上位置是第一个位置,下一个位置是第二个位置,依此类推。让我们看看输出(图 13-3 ):
图 13-3。
Multiple image grid
我们可以分离多通道图像的图像通道。代码(列表 13-12 )如下:
代码(清单 13-12 )的输出(图 13-4 )如下:
图 13-4。
Separate image channels
Note
为代码样本创建一个目录chapter 14。以下代码(清单 14-1 )演示了如何读取和显示图像:
输出(图 14-1 )如下:
图 14-1。
Reading and displaying an image
色彩映射表用于将颜色应用于数据集。灰度图像会自动应用默认色彩映射表。我们甚至可以为图像设置色彩映射表。为了正确显示灰度图像,我们需要像在前面章节中所做的那样,将色图设置为灰度值。在下面的例子中(清单 14-2 ,我们将使用默认的色彩映射表显示图像的一个通道。然后,我们将应用另一个色图到通道。
输出(图 14-2 )如下:
图 14-2。
Colormaps
我们还可以显示彩条,让观众知道图像中的相对强度值。以下代码(清单 14-3 )演示了:
输出(图 14-3 )如下:
图 14-3。
Colorbar demo
输出(图 14-4 )如下:
图 14-4。
Histogram demo
输出(图 14-5 )如下:
图 14-5。
Interpolation demo
在本章中,我们学习了如何用 matplotlib 表示数据。我们研究了色图、彩条和直方图。我们还学习了插值的概念。我们可以这样使用 matplotlib 来表示数据、图像和信号。
在本书中,我们从 Raspberry Pi 和单板计算机的基础知识开始。我们学习了如何设置树莓派 并将其连接到互联网。我们还学会了通过网络访问它。
然后我们继续学习超级计算和并行编程的基础知识。我们准备了 Pis 的节点,并通过一个网络将它们连接在一起,作为一个集群。我们还利用 MPI4PY 开发了集群的功能。
然后我们用 Python 学习了符号计算。我们还研究了用于数值计算的 NumPy 库。然后,我们探索了科学计算库 SciPy 及其在信号和图像处理中的应用。
最后,我们研究了如何用 matplotlib 库表示图像数据和计算直方图。
然而,这并不是结束。这仅仅是你在科学计算的神奇世界中旅程的开始。您可以进一步探索 matplotlib、OpenCV 和 Scientific Kit (SciKit)库。对于想尝试 OS 编程的人来说,他们可以在 Raspberry Pi 上用 C 语言探索 pthread 和 POSIX 库。有了树莓派,可能性是无穷无尽的。我祝你在开始这个神奇的探索之旅时一切顺利。