首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

定位您的应用程序 - 小端和大端 IBM XL Fortran 编译器的差异对您意味着什么(1)

定位您的应用程序 - 小端和大端 IBM XL Fortran 编译器的差异对您意味着什么(1)

简介要从大端编译器迁移到小端编译器,您可能需要更改一些代码,以便维持程序的行为或结果。在将代码从大端移植到小端时,应该考虑矢量、不同大小的项目之间的存储关联、16 位实数、复数和无格式数据文件等代码方面的差异。在 IBM Power Systems™ 上的小端 Linux® 版本使用了与大端版本不同的 ABI。此外,还需要更新对旧的 ABI 有依赖性的程序。新的内置函数使得针对矢量字节顺序的移植变得更容易。
本文将介绍在将用于 Power Systems 上的大端 IBM XL Fortran 的 Fortran 代码移植到 Power Systems 上的小端 IBM XL Fortran 时可能遇到的问题。本文对编码更改提出一些建议,还将介绍有助于移植代码的编译器特性和选项。
比较大端字节顺序和小端字节顺序字节顺序决定了在内存中如何解释数据。平台的字节顺序由处理器的架构决定。目前使用的两种最常见的字节顺序类型是大端字节顺序和小端字节顺序。
在大端平台(在这篇文章中通常简称为大端)上,内存中的字节排序是最大的字节排在首位(或 “左边”)。在小端平台(在这篇文章中通常简称为小端)上,内存和矢量寄存器中的字节排序是最小的字节排在首位(或 “左边”)。
例如,图 1 描述了在大端和小端平台上的内存中如何存储 000102030405060716(可被解释为一个 8 字节的整数)。在图 1 中,a 表示在该位置的内存地址。
图 1:内存中的大端和小端字节顺序的表示矢量IBM POWER® 处理器架构支持包含 16 个 1 字节元素、8 个 2 字节元素、4 个 4 字节元素或者两个 8 字节元素的 16 字节矢量。该处理器拥有 128 位的矢量寄存器,还提供了指令来将矢量加载到寄存器,操作寄存器中的矢量,并将矢量寄存器存储到内存。IBM XL 编译器提供了使用矢量的内置函数和语言支持。
在​​矢量元素顺序方面,大端和小端之间存在差异。为了帮助处理这些差异,我们还引入了新的编译器选项和内置函数。下面的章节中将会解释这些差异和新特性。
矢量元素顺序和矢量元素字节顺序在矢量寄存器中布置矢量元素的方式有两种。您可以从低到高加载元素,所以元素 0 是矢量寄存器中最左边的元素。另外,您也可以从高到低加载元素,使元素 0 是矢量寄存器中最右边的元素。前一种布置被称为 大端矢量元素顺序,而后者被称为 小端矢量元素顺序
在大端上,总是使用大端矢量元素顺序。
在小端上,您可以选择使用大端矢量元素顺序和小端矢量元素顺序。
不论采用哪一种矢量元素顺序,大端上的矢量元素都可以在内存中使用大端字节顺序。小端上的矢量元素默认情况下可以在内存中使用小端字节顺序。
为了说明大端和小端矢量元素顺序的差异,请看图 2 和图 3。
图 2 说明了如何在矢量寄存器中用大端矢量元素顺序表示 000102030405060708090A0B0C0D0E0F16(被解释为一个 16 字节的矢量)。图上的 b127 b0  标记分别表示寄存器的第 127 位和第 0 位。图中从上至下显示了用 1、2、4 和 8 字节的元素填充的矢量的表示。
图 2:矢量寄存器中的大端矢量元素顺序表示图 3 描述了如何在矢量寄存器中用小端矢量元素顺序表示 000102030405060708090A0B0C0D0E0F16(被解释为一个 16 字节的矢量)。图上的 b127 b0  标记分别表示寄存器的第 127 位和第 0 位。图中从上至下显示了用 1、2、4 和 8 字节的元素填充的矢量的表示。
图 3:矢量寄存器中的小端矢量元素顺序表示-qaltivec 选项-qaltivec 选项可用来告诉小端编译器如何在矢量寄存器中对矢量元素进行排序。
如果 -qaltivec=le,编译器将按照小端元素顺序来加载矢量,并假定按小端元素顺序将矢量加载到矢量存储。如果需要的话,编译器会插入矢量排列操作,以确保该加载和存储的内部过程使用的是小端元素顺序。对于引用特定元素的矢量内部过程,编译器假定是按小端元素顺序来加载矢量的。在小端上,-qaltivec=le 是默认值。
如果 -qaltivec=be,编译器将按照大端元素顺序加载矢量,并假定按大端元素顺序将矢量加载到矢量存储。如果需要的话,编译器会插入矢量排列操作,以确保该加载和存储的内部过程使用的是大端元素顺序。对于引用特定元素的矢量内部过程,编译器假定是按大端元素顺序来加载矢量的。
为了说明这个问题,请考虑下面的程序:
1
2
3
4
5
6
7
8
9
10
11
       program main
         vector(integer(8)) v
         integer(8) i(2)
         equivalence(v, i)

         i = [z'0001020304050607', z'08090A0B0C0D0E0F']

         print 1, "First vector element:", vec_extract(v, 0)
         print 1, "Second vector element:", vec_extract(v, 1)
1        format(A, z16.16)
       end program




在大端平台上编译这个程序时,或者在小端平台上用 -qaltivec=le 编译它时,会产生以下输出:
1
2
First vector element:0001020304050607
Second vector element:08090A0B0C0D0E0F




但是,如果在一个小端平台上用 -qaltivec=be 编译该程序,则会产生以下输出:
1
2
First vector element:08090A0B0C0D0E0F
Second vector element:0001020304050607




矢量被反向 加载到矢量寄存器中,而数组 i 中的元素顺序保持不变。
更简单的矢量使用方法是,使用下一节中介绍的 vec_xl、vec_xl_be、vec_xst 和 vec_xst_be 内部过程来进行加载和存储,而不是使用 EQUIVALENCE。请考虑下面的程序:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
vector(real(4)) v1, v2, v3, v4
real(4) a(4)

v1 = vec_xl(0, [real(4) ::1.0, 2.0, 3.0, 4.0])
call vec_xst(v1, 0, a)
print *, 'v1=', a

v2 = vec_neg(v1)
call vec_xst(v2, 0, a)
print *, 'v2=', a

!Merge high and low depend on vector element order
v3 = vec_mergeh(v1, v2)
call vec_xst(v3, 0, a)
print *, 'v3=', a

v4 = vec_mergel(v1, v2)
call vec_xst(v4, 0, a)
print *, 'v4=', a

end




该程序在大端平台和小端平台上产生了相同的输出。输出是:
1
2
3
4
v1= 1.000000000 2.000000000 3.000000000 4.000000000
v2= -1.000000000 -2.000000000 -3.000000000 -4.000000000
v3= 1.000000000 -1.000000000 2.000000000 -2.000000000
v4= 3.000000000 -3.000000000 4.000000000 -4.000000000

返回列表