运行时错误的诊断

程序可能会成功编译和链接,但在执行时产生意外的结果。编译器不能诊断不违反语言的语法的编程错误。本节描述一些常见错误、如何检测它们以及如何更正它们。

变量未初始化

具有自动存储器持续时间的对象是不会隐式初始化的,因此,它的初始值是不确定的。如果在设置它之前使用了 auto 变量,则每次运行程序时,它可能会也可能不会产生相同的结果。-qinfo=gen 编译器选项显示设置之前使用的 auto 变量的位置。-qinitauto 选项指示编译器将所有自动变量初始化为指定的值。此选项会降低应用程序的运行时性能,建议只用于调试。

运行时检查

-qcheck 选项将运行时检查代码插入到可执行文件中。这些子选项指定对空指针、数组下标超界和被零除的情况进行检查。与 -qinitauto 相似,-qcheck 会降低应用程序性能,建议只用于调试。

ANSI 别名判别

基于类型的别名判别(也称为 ANSI 别名判别)限制可安全地用来访问数据对象的左值。当在强制遵从语言标准的语言级别下进行编译时,在优化期间,C 和 C++ 编译器会强制使用基于类型的别名判别。ANSI 别名判别规则声明只能解除引用指向相同类型或兼容类型的指针。例外情况是符号和类型限定符不遵从基于类型的别名判别,并且字符指针可指向任何类型。将指针强制转换为不兼容的数据类型然后对它解除引用这种常见的编码作法违反了此规则。

通过设置 -qalias=noansi 关闭 ANSI 别名判别可更正程序行为,但是这样做会减少编译器优化应用程序的机会,从而降低了运行时性能。建议的解决方案是将程序更改为符合基于类型的别名判别规则。

#pragma option_override

有时,仅当使用优化时才会出现错误。最好(尤其是对于复杂的应用程序)是能对已知包含编程错误的函数关闭优化但允许对程序的其余部分进行优化。#pragma option_override 伪指令使您可以为特定函数指定其它优化选项。

#pragma option_override 伪指令还可用来确定产生该问题的函数。发现方法是有选择地对伪指令中的每个函数关闭优化直到问题消失为止。


共享内存并行化

提供了几项成熟技术以便可以并行执行程序并且使作业完成速度比在单处理器上运行更快。这些技术包括:

毫无疑问,应用程序的可移植性需求是选择要使用的最佳技术的因素。另外,该选择很大程度上取决于应用程序、程序员的技能和偏好以及目标机器的性能。在 AIX 上实现并行化的两种主要方法是通过使用手工编写的 POSIX 线程(pthread)和 OpenMP 伪指令。

AIX 操作系统的并行编程设施基于线程的概念。并行编程充分利用多处理器系统的优点,同时维护与现有单处理器系统的完全二进制兼容。这意味着在单处理器系统上运行的多线程程序可以利用多处理器系统而无需重新编译。

Pthread 在高效使用多处理器方面提供了很大的灵活性,这是因为它们提供了对并行化过程的最大程度的控制。这一平衡会明显增加代码的复杂性。在许多情况下,通过使用 OpenMP 伪指令、支持 SMP 的库或编译器的自动 SMP 功能的较简单方法更可取。显式使用线程不一定能得到更好的性能。调试多线程的应用程序尤其不可取。但是,在某些程序中,它是唯一适用的方法。

下面列示了不同技术的一些利弊。

编译器完成的自动并行化

支持 SMP 的库

OpenMP 伪指令

混合方法(OpenMP 和 pthread、或者 UNIX fork()exec() 并行化、特定于平台的构造的子集或混合)

pthread

OpenMP 伪指令

OpenMP 伪指令是一组命令,它们指导编译器应如何并行化特定循环。源代码中存在这些伪指令可使得编译器无需对并行代码执行任何并行分析。使用 OpenMP 伪指令要求存在 pthread 库以提供用于并行化的必要基础结构。

OpenMP 伪指令解决并行化应用程序的三个重要问题。第一,子句和伪指令可用于限定作用域的变量。通常,不应共享变量;即,每个处理器都应具有它自己的变量副本。第二,共享伪指令的工作指定应如何在 SMP 处理器中分发包含在代码的并行区域中的工作。最后,存在一些用于处理器之间的同步的伪指令。

编译器支持 OpenMP V2.0 规范。

相关参考

IBM Copyright 2003