高性能计算

编写CELL CPU上的高性能应用程序(第一部分zz)

2010年3月27日 阅读(444)

第 1 部分:简介 PLAYSTATION 3上的Linux

【转自IBM】Sony? PLAYSTATION? 3(PS3)对于程序员来说是尝试使用新 Cell Broadband Engine?(Cell BE)处理器进行开发最简单也是最经济的方法。本文将探索这个领域中的内容,介绍如何在 PS3 上安装 Linux?,如何开始在 PS3 上针对 Cell BE 处理器进行开发。

PLAYSTATION 3 是一款不同凡响的游戏机,原因有二。首先,与以往任何游戏机相比,它的开放性要好很多。大部分控制台都通过执行所有可能的操作来防止未经授权的游戏在其系 统上运行,而 PS3 却反其道而行之,甚至为安装并引导其他操作系统提供直接支持。当然,很多与游戏相关的特性,例如视频加速,并不对第三方操作系统开放,不过本系列关注的只 是一些通用和科学计算用应用程序(所以这些游戏特性并不重要)。

PS3 的中心是它的处理器 —— Cell Broadband Engine 芯片(通常称为 Cell BE 芯片)。Cell BE 体系结构与传统处理器的设计有根本的区别。Cell BE 处理器是由 9 个处理元素 构成的芯片(注意 PS3 上禁用了其中的一个,另外一个保留给系统使用,其他 7 个处理单元可用)。主处理元素是一个非常标准的通用处理器。这是一个双核的基于 PowerPC? 的元素,称为 Power Processing Element,或简称为 PPE。不过,另外 8 个处理元素与此完全不同。

Cell BE 中的其他处理元素称为 Synergistic Processing Elements,或简称为 SPE。每个 SPE 包括:

  • 一个向量处理器,称为 Synergistic Processing Unit,或 SPU
  • SPU 中的一个私有内存区域,称为本地存储(PS3 上这个区域的大小是 256K)
  • 用来联系外部世界的一组通信通道
  • 一组 128 个寄存器,每个 128 位宽(每个寄存器通常都可以用来同时保存 4 个 32 位的值)
  • 一个 Memory Flow Controller(MFC), 它负责管理 SPU 的本地存储和主存之间的 DMA 传输

不过,SPE 缺少一般处理器中的大部分通用特性。它们根本不能执行常见的操作系统任务。它们没有虚拟内存的支持,不能直接访问计算机的 RAM,中断支持也非常有限。SPE 处理器只专注于尽快处理数据。

因此,PPE 可以作为资源管理器使用,SPE 可以作为数据处理器使用。PPE 上的程序可以将任务分解到 SPE 上完成,然后相互传输数据。

将 SPE、PPE 和主存控制器连接在一起的是一个名为 Element Interconnect Bus 的总线。这是数据传输的主要通道。

这种设计最令人惊讶的地方是 SPE 的 256K 本地存储并不是缓存 —— 它实际上是 SPE 在给定时间为程序和数据提供的全部内存。这看起来似乎是个缺点,但是它实际上却具有以下几个好处:

  • 对本地存储内存的访问与主存访问相比速度更快。
  • 对本地存储内存的访问的预测可以精确到时钟周期级别上。
  • 可以异步请求将数据移入/移出内存,并可提前进行预测。

基本上,它具有缓存的全部速度优点。由于程序可以直接、显式地使用该内存,因此管 理方式更加智能。它可以请求数据在需要之间就被加载,然后可以在等待加载数据的同时继续执行其他任务。

尽管 Cell BE 处理器作为一种专用硬件已经存在很长一段时间了,但 PS3 是第一个较为经济并能可靠使用的基于 Cell BE 的设备。使用 Linux,任何人都可以在上面进行编程。

在 PS3 上运行 Linux?如何安装呢?

对于游戏机来说,允许在上面安装其他操作系统并不常见。由于控制台销售价格都很 低,因此它们通常都对系统进行了加锁以防止未向控制台开发者支付版税的游戏在上面运行。Sony 决定使自己的 PS3 控制台开放一些,允许在上面安装第三方操作系统,并同时警告这样做将不能获得图形加速。

由于这个原因,您现在才可以在 PS3 上安装 Linux。不过,需要费些周折,不过这的确可行。Terra Soft Solutions 已经与 Sony 公司合作特别为 PS3 开发了 Yellow Dog Linux 5。它甚至还为 PS3 上的发行版提供目前为止的独家支持。Yellow Dog Linux(也称为 YDL)从最初开始就是一个专用的基于 PowerPC 的发行版,因此 Sony 与它签约开发专用于 PS3 的下一个 YDL 版本也不足为奇。

下面介绍在 PS3 上安装 YDL 5 的操作步骤。

准备 PS3

要安装 Linux,需要几个额外硬件:

  • 显示设备和适当的电缆
  • USB 键盘
  • USB 鼠标
  • USB 闪盘

在显示设备上,有几个问题要格外注意。首先,20GB PS3 只提供了一个模拟复合 RCA 插口,用来连接电视之类的模拟输出设备。您可以通过一条专用的电缆将其转换成 VGA (更多信息请参看 参考资料)。 不幸的是,分辨率只能达 576×384。如果您希望获得更好的分辨率,就只能使用 HDMI 端口。然而,这会导致其他问题。通过一条电缆可以很容易地将 HDMI 转换成 DVI。因此它应该能够输入到兼容 DVI 的显示器上,对吗?但事实并非如此。这是因为有一种内容保护协议,称为 HDCP,当通过 HDMI 端口输出数据时,PS3 不会输出任何数据到不兼容 HDCP 的设备。因此,除非您的监视器是 HDCP 兼容的,否则就无法使用它来获得 PS3 上的数字输出信号,您只能使用 576×384 的分辨率(不过,据说使用组件视频输出而不是复合输出可以实现更高的分辨率)。

要准备 PLAYSTATION 3,请执行下面的步骤:

  1. 将以太网线连接到 PS3 上。请确保网络上已存在一个 DHCP 服务器。
  2. 如果这是一个新出厂的 PS3,请按照首次引导时的提示来进行设置,包括设置语言、时间和 PS3 系统使用的用户名。
  3. 转到 Settings,然后选择 System Settings,再选择 Format Utility
  4. 选择 Format Hard Disk, 并再次确认您的选择。
  5. 选择您希望使用的 Custom 分区模式。
  6. 选择希望 Allot 10GB to the Other OS。这会自动保留剩余的磁盘空间给 PS3 的游戏操作系统。在完成之后,就会重新启动系统。
  7. 当系统重新启动时,选择 Settings, 然后再选择 System Update
  8. 选择 Update via Internet
  9. 根据系统更新屏幕提示下载并安装最新的系统更新包。有些屏幕只有取消按 钮,而没有提示如何进一步操作。要在这些屏幕上继续向前运行,请使用控制器上的 X 按钮。
  10. 当 PS3 重新启动之后,接下来就可以在上面安装 Linux 了。

准备安装

现在可以开始准备 Linux 这边的东西了。下面是为了准备安装而需要在计算机上(而不是 PS3 上)执行的操作步骤:

  1. 下载并刻录 YDL 5 DVD ISO 文件。不能使用 CD 盘安装,PS3 只支持 DVD。
  2. 从 Sony 网站上下载 PS3 OtherOS 安装程序(请参看 参考资料), 并将其保存为 otheros.self。该文件在 PS3 游戏操作系统上运行来安装其他引导程序。
  3. 从 Terra Soft(同样请参看 参考资料) 上下载 YDL 引导程序,并将其保存为 otheros.bld。这是 Sony 安装程序要安装的引导程序。
  4. 将一个 USB 闪盘安装到计算机上。
  5. 在闪盘根目录中,创建一个名为 PS3 的目录。在这个 PS3 目录中,创建另外一个名为 otheros 的目录。
  6. 将所下载的另外两个文件(otheros.self 和 otheros.bld)复制到刚才在闪盘上创建的 PS3/otheros 目录中。

现在可以安装 Linux 系统了。

执行安装

执行以下步骤,将 Linux 安装到 PS3 上。

  1. 将闪盘从计算上拔出,并将其插入到 PS3 上。
  2. 转换到 Settings,然后选 择 System Settings,再选择 Install Other OS
  3. 请确认安装程序的位置,并按照屏幕提示执行后面的安装过程。请注意这只 安装了引导程序,而没有安装操作系统。
  4. 当安装程序完成时,切换到 Settings, 然后选择 System Settings,再选择 Default System。 然后选择 Other OS,再按 X 按钮。
  5. 插入 YDL 5 DVD。
  6. 插入 USB 键盘和鼠标。
  7. 现在重新启动系统。您可以通过按控制器上的 PS 按钮然后选择 Turn off the system 来重新启动系统,或者通过按电源按钮 5 秒钟来重新启动系统。之后系统就又启动起来了。
  8. 它重新引导时,看起来就像是在引导 Linux。这是因为这个引导程序实际上是一种裸 Linux 内核,称为 kboot。
  9. 在出现 kboot: prompt 时,如果您是通过 HDMI 端口输出的,就输入 de<installde<;如果是通过模拟方式输出的, 就输入 de<installtextde<。下述步骤假设您选用的是 installtext,不过区别不大。
  10. 在验证媒体之后,它可能会在屏幕上的蓝色区域显示一个 Traceback 错误。我们只需要忽略这个错误并按照安装屏幕的提示继续进行即可。
  11. 在看到询问分区问题时,不要担心它会删除 PS3 游戏操作系统。PS3 的 Other OS 模式只允许客户操作系统看到磁盘上自己使用的部分。即使是底层工具也看不到磁盘的其他部分。因此可以继续并让 YDL 删除磁盘上的所有数据,然后让它删除所有的分区并创建默认的分区布局。
  12. 在软件包的安装阶段,可能需要大约 1 个小时来安装软件包。然而,这不会安装整个 DVD。
  13. 在它重新引导时,如果您使用的是模拟输出,就需要在 kboot: boot 提示符后面输入 de<ydl480ide<。否则它就很可能会将输 出更改为模拟输出所不能支持的分辨率。
  14. 在它引导时,它会启动一个设置工具。现在您不需要做任何操作。如果您不 进行任何操作,它就会超时,然后完成引导过程。

现在一切就绪!YDL 5 已经安装到 PS3 上了!

安装后的设置

安装程序并不会关注所有细节,尤其是对于模拟显示设备来说更是如此。如果您希望实 现一些功能,例如自动使用正确的分辨率来引导系统,则需要再执行几个步骤,在模拟设备上配置 X Window System,安装 Cell BE SDK。要执行这些步骤,需要确保 YDL 5 DVD 已经在驱动器中,并这样挂载它:

mount /dev/dvd /mnt

后面所有的操作都假设安装 DVD 是这样挂载的,而且您是以 root 用户身份登录的。

要让模拟系统在启动时就引导到正确的分辨率,请编辑文件 /etc/kboot.conf,将 de<default=ydlde< 这行内容修改为 de<default=ydl480ide< 并保存文件。

如果您希望为自己的模拟设备配置 X Window System,就需要按照下面的方式来安装并运行 Xautoconfig 包:

rpm -i /mnt/YellowDog/RPMS/Xautoconfig-*
Xautoconfig

现在您可以通过运行 startx 来启动 X Window System,不过在模拟设备上您的屏幕就会显得有些太小了。下面是可以帮助您在这样小的设备上进行操作的一个快速提示:即使看不到标题条,按下 alt+ 鼠标左键 也可以让您在桌面上拖动屏幕。

如果您希望自己的系统在系统引导时就有一个图形化的登录界面,就需要编辑 /etc/inittab 文件。将 de<id:3:initdefault:de< 行的内容修改为 de<id:5:initdefault:de< 并保存文件。现在当重新启动系统时,就会出现一个很好的图形化登录界面。记住在重新启动系统之后,还要像前面一样挂载 DVD 才能完成其余的步骤。注意 Nautilus 实际上会将其挂载到一个不同的位置,因此如果您使用了 Nautilus 来挂载自己的 DVD,它会挂载到 /media/CDROM 上,而不是 /mnt 处。

现在让我们来安装 Cell BE SDK V2.0。要查看它是否已经被安装程序安装了,可以简单地执行 de<which spu-gccde<。 如果找不到这个程序,那么 SDK 就没有安装。要安装它,需要执行下面的命令:

cd /mnt/YellowDog/RPMS
rpm -i spu-binutils-* spu-gcc-* spu-gdb-* spu-utils* libspe-devel-*

然而,有一组重要的包在 DVD 中并没有包括,它就是 64 位版本的 libspe。这个问题很容易解决。可以从资源 DVD 或 Web 站点上下载 libspe 的 SRPM(名为 libspe-1.1.0-1.src.rpm)。然后到下载目录中执行下面的步骤:

rpm -i libspe-*.src.rpm
cd /usr/src/yellowdog/SPECS
rpmbuild -bb –target ppc64 libspe.spec
cd ../RPMS/ppc64
rpm -i elfspe-* libspe-*

现在您已经做好所有的准备了。YDL 已经安装、配置好并且可以运行了!

您可能会疑惑如何回到游戏操作系统中呢?因为您可能会希望玩 PS3 上的一两个游戏。要回到游戏操作系统,请在 kboot: 提示符或命令行上输入 de<boot-game-osde< 。如果由于某些原因 Linux 产生了错误,或者没有加载,那么您可以通过关闭 PS3 来加载游戏操作系统,然后在启动系统时长按开关键 5 秒钟(直到听到一声蜂鸣)。这两种方法都可以加载游戏操作系统,但是这也会将默认操作系统设置为游戏操作系统。因此,要恢复到 Linux 系统,需要回到前面的设置过程,并设置它默认从 Other OS 引导。

编写CELL CPU上的高性能应用程序(第一部分zz) - 星星 - 银河里的星星
编写CELL CPU上的高性能应用程序(第一部分zz) - 星星 - 银河里的星星 编写CELL CPU上的高性能应用程序(第一部分zz) - 星星 - 银河里的星星

好的,我们已经安装好 Linux 了。接下来应该做什么呢?

现在您已经完全安装好 Linux 和 Cell BE SDK 了,本系列文章接下来的部分是关于它的编程和使用的。为了对这些内容有个初步的了解,请参看下面这个用 C 编写的演示程序,该程序利用了 PPE 和 SPE。

在了解这是如何工作的之前,请先来看一下编译 Cell BE 程序所使用的一些通用工具:

  • gcc
    可信赖的编译器,用来为 PPE 生成 PPC Linux 二进制程序。使用 -m64 开关可以生成 64 位可执行程序。
  • spu-gcc
    这也是 可信赖的一个编译器,它可以为 SPE 生成代码。
  • embedspu
    这是一个特殊工具,可以将 SPE 程序转换成一个能被链接进 PPE 可执行程序的对象文件。它还会创建一个引用 SPE 程序的全局变量,这样 PPE 就能够将程序加载到 SPE 中并根据需要来运行程序了。要嵌入到 64 位 PPC 程序中,请使用 -m64 标记。

如果没有 SPE,Cell BE 处理器的编程与其他基于 PowerPC 系统会十分类似。实际上,您可以假装 SPE 不存在,代码依然可以很好地工作。不过,这样就会导致有很多计算能力没有被充分利用。要充分利用 SPE 的优点,您只能多费点精力。

如果您是新接触 Cell BE 技术,请记住 PPE 是系统的资源管理器。它负责处理操作系统任务、管理对内存的访问并控制 SPE 的工作。PPE 的代码会负责对程序进行初始化、给一个或多个 SPE 设置任务并执行输入输出操作。当然,PPE 也可以执行处理任务,不过通常都是将任务合理地分配给 SPE 执行。

因此,让我们来了解一下简单程序是如何构造来在 SPE 上执行处理任务的。这个程序非常基本 —— 它计算在给定速度(单位为每小时英里数)和时间(单位为小时)情况下的旅行距离。下面是 PPE 的代码(请将其输入到 de<ppe_distance.cde< 中):

清单 1. 方程求解的 PPE 代码
#include <stdio.h>
#include <libspe.h>

//This global is for the SPE program code itself. It will be created by
//the embedspu program.
extern spe_program_handle_t calculate_distance_handle;

//This struct is used for input/output with the SPE task
typedef struct {
float speed; //input parameter
float num_hours; //input parameter
float distance; //output parameter
float padding; //pad the struct a multiple of 16 bytes
} program_data;

int main() {
program_data pd __attribute__((aligned(16))); //aligned for transfer

//GATHER DATA TO SEND TO SPE
printf("Enter the speed at which your car is travelling in miles/hr: ");
scanf("%f", &pd.speed);
printf("Enter the number of hours you have been driving at that speed: ");
scanf("%f", &pd.num_hours);

//USE THE SPE TO PROCESS THE DATA
//Create SPE Task
speid_t spe_id = spe_create_thread(0, &calculate_distance_handle, &pd, NULL,
-1, 0);
//Check For Errors
if(spe_id == 0) {
fprintf(stderr, "Error creating SPE thread!\n");
return 1;
}
//Wait For Completion
spe_wait(spe_id, NULL, 0);

//FORMAT THE RESULTS FOR DISPLAY
printf("The distance travelled is %f miles.\n", pd.distance);
return 0;
}

正如前面介绍的一样,Cell BE 处理器中的 PPE 的主要任务是处理输入和输出任务。真正有趣的部分是 de<spe_create_threadde<。 第一个参数是一个线程组 ID(0 表示应该为这个线程创建一个新组),第二个参数是 SPE 程序的句柄,第三个参数是指向要传输的数据的指针,第四个参数是一个可选的环境指针,第五个参数是运行程序希望使用的 SPE 的掩码(-1 表示可以使用任何可用的 SPE),最后一个参数是希望采用的选项的列表(在本例中,未使用任何选项)。这个函数返回 SPE 任务的 ID 号,然后您可以将它作为 de<spe_waitde< 的参数使用。de<spe_waitde< 在 SPE 任务结束时返回。

下面是 SPE 的代码(请将其输入到 de<spe_distance.cde< 中):

清单 2. SPE 计算的例子
//Pull in DMA commands
#include <spu_mfcio.h>

//Struct for communication with the PPE
typedef struct {
float speed; //input parameter
float num_hours; //input parameter
float distance; //output parameter
float padding; //pad the struct a multiple of 16 bytes
} program_data;

int main(unsigned long long spe_id, unsigned long long program_data_ea, unsigned
long long env) {
program_data pd __attribute__((aligned(16)));
int tag_id = 0;

//READ DATA IN
//Initiate copy
mfc_get(&pd, program_data_ea, sizeof(pd), tag_id, 0, 0);
//Wait for completion
mfc_write_tag_mask(1<<tag_id);
mfc_read_tag_status_any();

//PROCESS DATA
pd.distance = pd.speed * pd.num_hours;

//WRITE RESULTS OUT
//Initiate copy
mfc_put(&pd, program_data_ea, sizeof(program_data), tag_id, 0, 0);
//Wait for completion
mfc_write_tag_mask(1<<tag_id);
mfc_read_tag_status_any();
return 0;
}

后续文章将更加深入地介绍 SPU 编程的知识,这里只简单介绍一下。作为第 3 个参数传递到 de<spe_create_threadde< 的指针会以 de<program_data_eade< 的形式进入这个程序。EA 表示有效地址,这是从主 PPE 程序中看到的主存地址。由于 SPE 不能直接访问主存,所以无法直接将其作为一个指针废弃。相反,您必须发起一个传输请求将数据复制到本地存储中。一旦数据保存到本地存储中,就可以通过 本 地存储地址(local store address,有时简写为 LSA) 来访问这些数据。

de<mfc_getde< 发起到本地存储的传输。注意在 PPE 和 SPE 中,这个结构被对齐为 16 字节,并填充成 16 个字节。在下一篇文章中我们将更详细地介绍这方面的内容,但是对于大部分 DMA 传输来说,都必须 按照 16 字节边界对齐,并且大小应该是 16 字节的整数倍。de<tag_idde< 让您可以检索 DMA 操作的状态。在传输之后,接下来的两个函数可以导致程序等待,直到传输完成为止。

主要的处理过程非常简单 —— 只需用速度乘以时间即可。在数据处理完之后,de<mfc_putde< 会发起一个传输,传回主存,接下来的两个函数会让您等待 DMA 操作完成。当所有这些操作完成之后,程序退出。

现在您需要编译并运行这个程序。这实际上非常简单:

#Compile the SPE program
spu-gcc spe_distance.c -o spe_distance
#Embed the SPE program into an ELF object file, and expose it
#through the global variable: calculate_distance_handle
embedspu calculate_distance_handle spe_distance spe_distance_csf.o
#Compile the PPE program together with the SPE program
gcc ppe_distance.c spe_distance_csf.o -lspe -o distance
#Run the program
./distance

现在您就拥有了一个可以良好运行的 Cell BE 程序。

编写CELL CPU上的高性能应用程序(第一部分zz) - 星星 - 银河里的星星
编写CELL CPU上的高性能应用程序(第一部分zz) - 星星 - 银河里的星星 编写CELL CPU上的高性能应用程序(第一部分zz) - 星星 - 银河里的星星

结束语

尽管您不能直接在 PS3 上编程,但是 PS3 支持第三方的操作系统,这就让您可以将 Linux 安装到 PS3 上。将 Linux 安装到 PS3 上需要您付出一点努力,但这很值得,因为最终您将获得一个低成本并能良好运行的 Cell BE 处理器。本系列的后续文章将深入介绍 Cell BE 编程以及如何充分利用可从 SPE 获得的每一点速度。

You Might Also Like