【GraphBLAS笔记】(一)GraphBLAS C API的基本概念

基本概念

GraphBLAS C API用于构造用“线性代数语言”表示的图算法。图被表示为矩阵,并通过使用半环代数结构推广了这些矩阵上的运算。在本章中,我们将定义用于定义GraphBLAS C API的基本概念。我们提供以下元素:

1. 本文件使用的术语表和表示法。

2. 该API的代数结构和相关的算术基础。

3. GraphBLAS代数结构中出现的函数及其管理方式。

4. GraphBLAS中元素的域。

5. 索引、索引数组、标量数组和用于公开GraphBLAS对象内容的外部矩阵格式。

6. GraphBLAS不透明对象。

7. GraphBLAS C规范中隐含的执行和错误模型。

8. API使用的枚举及其值。


2.1 术语汇编

2.1.1 GraphBLAS API的基本定义

application : 一个从GraphBLAS C API调用方法来解决问题的程序。

GraphBLAS C API : 完整定义到GraphBLAS的C绑定的类型、对象、文字和其他元素的应用程序编程接口。

function : 指C编程语言中命名的一组语句。方法、操作符和用户定义函数通常是用C函数实现的。当提及程序员编写的代码时,与函数作为GraphBLAS元素的角色相反,它们可以这样被提及。

method: GraphBLAS C API中定义的一个函数,用于操作GraphBLAS对象或GraphBLAS API实现的其他不透明特性。

operator: 对GraphBLAS矩阵和向量中存储的元素执行操作的函数。

GraphBLAS operation: GraphBLAS数学规范中定义的数学操作。这些操作(不要与运算符混淆)通常作用于具有代数半环定义元素的矩阵和向量。


2.1.2 GraphBLAS对象及其结构

non-opaque datatype: 公开其内部结构并可由用户直接操作的任何数据类型。

opaque datatype: 任何隐藏其内部结构且只能通过API操作的数据类型。

GraphBLAS object: GraphBLAS C API定义的不透明数据类型的实例,只能通过GraphBLAS API进行操作。GraphBLAS不透明对象有四种: domains(域,即类型)、algebraic objects (代数对象,运算符、半群和半环)、collections (集合,标量、向量、矩阵和掩码) 和 descriptors(描述符)。

handle: 一个变量,它保存对GraphBLAS不透明对象之一的实例的引用。这个变量的值包含对GraphBLAS对象的引用,但不包含对象本身的内容。因此,给另一个变量赋值会将引用复制到一个句柄的GraphBLAS对象,但不会复制对象的内容。(C中的handle类似于C++中对象的指针)

domain: 存储在GraphBLAS集合中或由GraphBLAS操作符操作的元素的一组有效值。注意,有些GraphBLAS对象涉及将一个或多个输入域中的值映射到输出域中的值的函数。这些GraphBLAS对象将具有多个域。

collection: 一个不透明的GraphBLAS对象,它保存来自指定域的许多元素。由于这些对象基于不透明的数据类型,GraphBLAS C API的实现具有针对特定平台优化数据结构的灵活性。GraphBLAS对象通常实现为稀疏的数据结构,这意味着只存储具有值的元素子集。

implied zero: 在GraphBLAS向量或矩阵中具有有效索引(或多个索引),但在该向量或矩阵的元素列表中没有显式标识的任何元素。从数学的角度来看,隐零被视为具有相关的单半环或半环的零元素的值。然而,GraphBLAS操作是有目的地使用集合表示法定义的,这样就不需要对隐含的零进行推理。因此,GraphBLAS方法和运算符的定义中没有使用这个概念。

mask: 一个内部GraphBLAS对象,用于控制如何将值存储在方法的输出对象中。掩码只存在于方法内部;因此,它被称为内部不透明对象。掩码由作为方法掩码参数输入的集合对象(向量或矩阵)的元素组成。

GraphBLAS允许两种类型的掩码:

(1)在默认情况下,当掩码的值转换为布尔类型时,计算结果为true时,为输入集合对象中存在的每个元素都存在一个掩码的元素。

(2)在只有结构的情况下,掩码有结构但没有值。输入集合描述了一种结构,在这种结构中,掩码的元素为存储在输入集合中的每个元素存在,而不管其值如何。

complement: GraphBLAS掩码M的补充是另一个掩码M',其中M'中的元素是来自M的那些不存在的元素。


2.1.3 在GraphBLAS中使用的代数结构

associative operator (关联运算符):在一个二元运算符连续使用两次或多次的表达式中,如果无论操作的分组方式如何(不改变其顺序),结果都不变,则该运算符是关联的。换句话说,在使用相同关联运算符的二进制操作序列中,括号的合法位置不会改变序列操作产生的值。当应用于有限精度的数字(例如浮点数)时,在无限精度数字(例如实数)上具有关联性的运算符不是严格关联的。例如,这种非关联性是由于舍入错误或某些数字不能精确表示为浮点数这一事实造成的。在GraphBLAS规范中,与计算中的常见做法一样,当运算符对无限精确数的数学定义是关联的时,我们将其称为关联运算符,即使当应用于有限精度数时,它们只是近似关联的。没有GraphBLAS方法会暗示对任何关联运算符进行预定义分组。鼓励GraphBLAS的实现利用关联性来优化具有此要求的任何GraphBLAS方法的性能。即使GraphBLAS方法的定义暗示了关联操作的固定顺序,这一点仍然成立。

commutative operator (交换运算符):在使用二元运算符的表达式中(通常连续两次或多次),如果无论输入操作的顺序如何,结果都不变,则该运算符是可交换的。没有GraphBLAS方法会暗示对任何交换运算符的预定义排序。鼓励GraphBLAS的实现利用交换性来优化具有此要求的任何GraphBLAS方法的性能。即使GraphBLAS方法的定义意味着交换操作的顺序是固定的,这也适用。

GraphBLAS operators (GraphBLAS运算符):作用于GraphBLAS对象元素的二进制或一元运算符。GraphBLAS运算符用于表示GraphBLAS中使用的代数结构,例如幺半群和半环。它们还用作几个GraphBLAS方法的参数。GraphBLAS运算符有两种类型:(1)预定义运算符(2)使用GrB_UnaryOp_new()或GrB_BinaryOp_now()创建的用户定义运算符。

 ​​​​​​monoid (幺半群): 一种代数结构,由一个域、一个结合二元运算符和该运算符的恒等式组成。GraphBLAS幺半群有两种类型:(1)预定义幺半群(2)使用GrB_Monid_new()创建的用户定义的幺半群。

semiring (半环):一种代数结构,由一组允许值(域)、一个称为加法的交换和关联二元运算符、一个名为乘法的二元运算符(其中乘法分布于加法之上)以及一个名在加法(0)和乘法(1)之上的恒等式组成。加法恒等式是乘法上的零化子。

GraphBLAS semiring (GraphBLAS半环):  允许偏离半环在数学上严格的定义,因为域、运算符和单位元的某些组合在图算法中很有用,即使它们与半环的数学定义不严格匹配。GraphBLAS半环有两种类型:(1)预定义半环(2)使用GrB_Semiring_new()创建的用户定义的半环。

index unary operator (索引一元运算符):一元运算符的变体,它对GraphBLAS向量和矩阵的元素以及表示它们在对象中位置的索引值进行操作。索引一元运算符有两种类型:(1)预定义的索引一元运算符(2)使用GrB_IndexUnaryOp_new创建的用户定义运算符。


2.1.4 使用GraphBLAS C API执行应用程序

program order (程序顺序):GraphBLAS方法在线程中调用的顺序,由程序文本定义。

host programming environment (主机编程环境):GraphBLAS规范定义了一个API。API中的函数出现在程序中。此程序是使用GraphBLAS之外定义的编程语言和执行环境编写的。我们将此编程环境称为“主机编程环境”

execution time (执行时间):执行程序定义的指令所花费的时间。此术语在本规范中专门用于代表GraphBLAS方法调用执行的计算上下文。

sequence (顺序):GraphBLAS应用程序根据程序顺序唯一地定义GraphBLAS方法调用的有向非循环图(DAG)。在程序中的任何点上,任何GraphBLAS对象的状态都由该DAG的子图定义。GraphBLAS方法的有序集合按程序顺序调用,定义特定对象的子图是该对象的序列。

complete (完成): 当GraphBLAS对象可以用于与在另一个线程上读取变量的方法调用的发生前关系时,该对象就是完整的。在多线程程序中推理内存顺序时使用此概念。在一个线程上定义的完整GraphBLAS对象可以在第二个线程的方法调用中安全地用作IN或INOUT参数,前提是方法调用已正确同步,因此第一个线程上的定义在第二线程上使用之前发生。在阻塞模式下,对象在写入该对象的GraphBLAS方法调用返回后即完成。在非阻塞模式下,对象在使用GrB_complete参数调用GrB_wait()方法后完成。

materialize (具体化):当GraphBLAS对象(1)完成时,(2)由定义该对象的序列定义的压缩已完成(完全完成或因错误而停止),并且不会消耗任何额外的计算资源时,(3)根据GraphBLAS错误模型,可以读取与该序列关联的任何错误时,该对象即被具体化。从未加载到非不透明数据结构中的GraphBLAS对象可能永远不会具体化。例如,如果与对象关联的操作被支持GraphBLAS C API实现的运行时系统融合或以其他方式更改,则可能会发生这种情况。对象可以通过调用GrB_wait()方法的物化模式来物化。

context (上下文):应用程序看到的GraphBLAS C API实现的实例。应用程序的开始和结束之间只能有一个上下文。上下文以调用GrB_init()的第一个线程开始,以调用GrB_finalize()的第二个线程结束。在应用程序中多次调用GrB_init()或GrB_finalize()是错误的。上下文用于约束GraphBLAS C API实现实例的行为,并支持各种执行策略。目前,上下文上唯一支持的约束与程序执行模式有关。

program execution mode (程序执行模式):定义GraphBLAS序列的执行方式,并与GraphBLASC API实现的上下文关联。它由调用GrB_init()的应用程序设置为两种可能状态之一。在块模式下,GraphBLAS方法在计算完成且所有输出对象都已具体化后返回。在非阻塞模式下,一旦参数被测试为与方法一致(即没有API错误),并且可能在进行任何计算之前,方法就会返回。


2.1.5 GraphBLAS方法:行为和错误条件

implementation-defined behavior (实现定义的行为):必须由实现记录并允许在不同的兼容实现之间变化的行为。

undefined behavior (未定义的行为):GraphBLAS C API未指定的行为。一致性实现可以自由选择行为未定义的方法的结果。

thread-safe (线程安全):考虑一个从多个线程调用的函数,其参数在内存中不重叠(即参数列表不共享内存)。如果函数是线程安全的,那么当由多个线程并发执行或在单个线程上顺序执行时,它的行为将相同。

dimension compatible (维度兼容):作为参数传递给GraphBLAS方法的GraphBLAS对象(矩阵和向量)与维度(或形状)兼容,前提是它们具有正确的维度数和每个维度的大小,以满足与方法关联的操作的数学定义规则。如果违反了上述任何维度兼容性规则,GraphBLAS方法的执行将结束,并返回GrB_dimension_MISMATCH错误。

domain compatible (域兼容): 两个域,其中一个域的值可以根据C语言的规则转换为另一个域中的值。特别是,表3.2中的域都彼此兼容,而用户定义类型中的域只与自身兼容。如果违反了上述任何域兼容性规则,GraphBLAS方法的执行将结束,并返回GrB_domain_MISMATCH错误。


2.2 符号


2.3 数学基础

图形可以用矩阵表示。存储在这些矩阵中的值对应于图中边的属性(通常是权重)。1同样,图中顶点的信息存储在向量中。可以存储在矩阵或向量中的有效值集称为其域。矩阵通常是稀疏的,因为两个顶点之间缺少边意味着矩阵中的相应位置没有存储任何内容。向量可能是稀疏的或密集的,或者它们可能从稀疏开始,随着算法遍历图形而变得密集。

GraphBLAS C API规范定义的操作对这些矩阵和向量进行操作,以执行图形算法。这些GraphBLAS操作是根据GraphBLAS-半环代数结构定义的。修改底层半环会更改操作的结果,以支持多种图形算法。在给定算法中,更改适用于矩阵运算的GraphBLAS半环通常是有益的。这对GraphBLAS API的C绑定有两个含义。

首先,这意味着我们为半环定义了一个单独的对象以传递给方法。由于在许多情况下不需要完整的半环,因此我们还支持传递幺半群或甚至二元运算符,这意味着半环是隐含的,而不是显式声明的。

其次,改变半环的能力会影响矩阵或向量稀疏表示中隐含零的含义。实数运算中的这个元素是零,这是加法运算符和乘法运算符的零化子的恒等式。随着半环的变化,这意味着新半环的加法算子和乘法算子的零化子(如果存在)的恒等式将发生零变化。对于稀疏矩阵或向量中存储的内容,没有任何变化,但其中隐含的零会随着特定操作而变化。在所有情况下,隐含零的性质都无关紧要,因为GraphBLAS C API要求实现将它们视为矩阵或向量中不存在的元素。

与矩阵和向量一样,GraphBLAS半环具有与其输入和输出相关联的域。GraphBLAS C API中的半环由两个与输入操作数关联的域和一个与输出关联的域定义。在GraphBLAS C API中使用时,这些域可能与操作中提供的矩阵和向量的域不匹配。在这种情况下,API只支持有效的域兼容转换。

线性代数语言中图形运算的数学形式通常假设我们可以在实数域中运算。然而,GraphBLAS C绑定是为在计算机上实现而设计的,计算机必须有有限的位来表示数字。因此,我们要求在需要表示实数的地方使用浮点数,如IEEE-754标准定义的浮点数(单精度和双精度)。这些有限精度数的实际含义是,随着操作中的操作数分组(由于关联性)的变化,一系列计算的结果可能会随着一次执行而变化。虽然已知技术可以减少这些影响,但我们不需要甚至不期望实现使用它们,因为它们可能会增加相当大的开销。在大多数情况下,这些舍入误差并不显著。当它们很重要时,问题本身就是病态的,需要重新制定。


2.4 GraphBLAS不透明对象 

GraphBLAS标准中定义的对象包括类型(元素域)、元素集合(矩阵、向量和标量)、这些元素上的运算符(一元、索引一元和二元运算符)、代数结构(半环和幺半群)和描述符。GraphBLAS对象定义为不透明类型;也就是说,它们仅通过GraphBLAS应用程序编程接口进行管理、操作和访问。这为GraphBLAS C规范的实现提供了灵活性,可以针对不同的场景优化对象或满足不同硬件平台的需求。

GraphBLAS不透明对象通过其句柄进行访问。句柄是引用表2.1中某一类型实例的变量。GraphBLAS规范的实现在如何实现这些句柄方面具有很大的灵活性。所需要的只是句柄对应于C语言中定义的类型,该类型支持等式的赋值和比较。GraphBLAS规范定义了对每种类型有效的文本GrB_INVALID_HANDLE。使用C中的逻辑相等运算符,必须能够将句柄与GrB_INVALID_handle进行比较,以验证句柄是否有效。

每个GraphBLAS对象都有一个生存期,它由对象的创建和销毁之间按程序顺序执行的指令序列组成。GraphBLAS C API预定义了许多这样的对象,这些对象是在通过调用GrB_init初始化GraphBLAS上下文时创建的,而在通过调用GrB_finalize终止GraphBLAS上下文时销毁的。

使用GraphBLAS API的应用程序可以通过为其将使用的对象声明表2.1中适当类型的变量来创建其他对象。在使用之前,必须通过调用对象各自的构造函数方法之一来初始化对象。每种对象至少有一个形式为GrB_*_new的显式构造函数方法,其中“*”替换为对象类型(例如GrB_Semiring_new)。请注意,某些对象,尤其是集合,具有其他构造函数方法,例如复制、导入或反序列化。调用构造函数显式创建的对象应通过调用GrB_free销毁。在预定义对象上调用GrB_free的程序的行为未定义。

这些构造函数和析构函数方法是唯一更改句柄值的方法。因此,通过这些方法更改的对象将作为指针传递到方法中。在所有其他情况下,句柄不会被方法更改,而是通过值传递。例如,即使在矩阵相乘时,当输出乘积矩阵的内容发生变化时,该矩阵的句柄也保持不变。

一些GraphBLAS构造函数方法将其他对象作为输入参数,并使用这些对象创建新对象。对于所有这些方法,所创建对象的生存期必须严格在任何依赖输入对象的生存期限之前结束。例如,向量构造函数GrB_vector_new将GrB_Type对象作为输入。在销毁创建的向量之前,不得销毁该类型对象。类似地,GrB_Semiring_new方法将一个幺半群和一个二进制运算符作为输入。在创建的半环被销毁之前,这两者都不能被销毁。

请注意,一些构造函数方法(如GrB_Vector_dup和GrB_Matrix_dup)的行为不同。在这些情况下,一旦调用返回,输入向量或矩阵就会被销毁。但是,在销毁GrB_vector_dup或GrB_matrix_dup创建的向量或矩阵之前,无法销毁用于创建输入向量或矩阵的原始类型对象。此行为必须适用于任何复制构造函数链。

使用GraphBLAS句柄的程序员必须小心区分句柄和通过句柄操作的对象。例如,一个程序可以声明两个相同类型的GraphBLAS对象,初始化其中一个,然后将其分配给另一个变量。但是,该赋值仅将句柄分配给变量。它不会创建该变量的副本(为此,需要使用适当的复制方法)。如果稍后通过使用第一个变量调用GrB_free来释放对象,则对象将被销毁,第二个变量将引用不再存在的对象(所谓的“悬垂句柄”)。

除了通过句柄操作的不透明对象外,GraphBLAS C API还将其他不透明对象定义为内部对象;也就是说,对象永远不会作为变量在应用程序中公开。此不透明对象是用于控制哪些计算值可以存储在GraphBLAS操作的输出操作数中的掩码。第3.5.4节描述了面罩。


2.5 执行模型

使用GraphBLAS C API的程序称为GraphBLAS应用程序。应用程序构造GraphBLAS对象,操纵它们以实现图形算法,然后从GraphBLAS对象中提取值以生成该算法的结果。在GraphBLAS C API中定义的操作GraphBLAS对象的函数称为方法。如果该方法对应于GraphBLAS数学规范中定义的一个操作,我们将该方法称为操作。

GraphBLAS应用程序指定GraphBLAS方法调用的有序集合,这些方法调用由它们在程序文本中的出现顺序(程序顺序)定义。它们定义了一个有向非循环图(DAG),其中节点是GraphBLAS方法调用,边是方法调用之间的依赖关系。

DAG中的每个方法调用都唯一且明确地定义了输出GraphBLAS对象,只要没有使对象处于无效状态的执行错误(请参阅第2.6节)。方法调用的有序集合是应用程序整体DAG的子图,它定义了GraphBLAS对象在程序中任意点的状态。此有序集合是该对象的序列。

由于GraphBLAS执行是根据DAG定义的,并且GraphBLAS对象是不透明的,因此GraphBLAS规范的语义为实现提供了相当大的灵活性,以优化性能。GraphBLAS实现可以延迟DAG中节点的执行,融合节点,甚至替换DAG中的整个子图以优化性能。当我们描述阻塞和非阻塞执行模式时,我们将在第2.5.1节中进一步讨论这个主题。

正确的GraphBLAS应用程序必须无竞争。这意味着应用程序生成的DAG和执行该DAG生成的结果必须相同,无论线程的执行计划如何。应用程序程序员负责控制内存顺序并建立所需的同步关系,以确保多线程GraphBLAS应用程序的无争用执行。编写无竞争GraphBLAS应用程序将在第2.5.2节中进一步讨论。


2.5.1执行模式

GraphBLAS应用程序定义的DAG的执行取决于GraphBLAS程序的执行模式。有两种模式:阻塞和非阻塞。

blocking: 在阻塞模式下,每个方法都会完成该方法定义的GraphBLAS操作,并且在继续执行下一条语句之前,所有输出GraphBLAS对象都会被具体化。即使是打破GraphBLAS对象不透明性的机制(例如,性能监视器、调试器、内存转储)也会观察到操作已完成。

nonblocking: 在非阻塞模式下,一旦检查并验证输入参数以定义格式良好的GraphBLAS操作,每个方法都可以返回。(也就是说,没有API错误;请参阅第2.6节。)GraphBLAS方法可能尚未完成,但输出对象已准备好供下一个GraphBLAS方法调用使用。如果需要,可以使用GrB_COMPLETE 或 GrB_MATERIALIZE 调用 GrB_wait 来强制GraphBLAS对象(obj)的序列完成其执行。

当定义库调用的上下文时,执行模式在GraphBLAS C API中定义。这在调用GrB_init()函数调用任何GraphBLAS方法之前发生一次。此函数接受GrB_Mode类型的单个参数,其值如表3.1(a)所示。

在非阻塞模式下执行的应用程序不需要在验证输入参数后立即返回。在非阻塞模式下运行的GraphBLAS C API的一致性实现可以选择以阻塞模式执行。非阻塞模式下的一系列操作,其中每个带有输出对象obj的GraphBLAS操作后面都有一个 GrB_wait(obj,GrB_MATERIALIZE)调用,与删除 GrB_wait(obj,GrB_MATERIALIZ)调用的阻塞模式下相同的序列等效。

非阻塞模式允许任何满足序列数学定义的执行策略。这些方法可以放入队列中并延迟。它们可以链接在一起并融合在一起(例如,用矩阵三乘积替换链接的矩阵乘积对)。只要最终结果符合程序顺序中出现的GraphBLAS方法调用序列所提供的数学定义,懒惰求值、贪婪求值和异步执行都是有效的。

阻塞模式强制实现精确执行由方法定义的GraphBLAS操作,并分别完成每个方法调用。它对于调试或在外部工具(如调试器)需要在一系列操作期间评估内存状态的情况下非常有用。

在没有执行错误且输入对象条件良好的操作序列中,除与浮点运算相关的舍入错误所产生的影响外,阻塞和非阻塞模式的结果应相同。由于在使用非阻塞模式时实现具有极大的灵活性,我们希望以非阻塞模式执行序列可以在更短的时间内完成执行。

值得注意的是,GraphBLAS中从不延迟非不透明对象的处理。也就是说,不管执行模式如何,使用非不透明对象的方法(例如GrB_Matrix_build(),第4.2.4.9节)和生成非不透明的对象的方法,例如GrB_Matrix_extractTuples(),第一节4.2.4.13)总是在返回之前完成使用或生成这些非不透明物体。

最后,在进行了所有GraphBLAS方法调用之后,通过调用GrB_finalize()终止上下文。在GraphBLAS C API的当前版本中,在执行程序时只能设置一次上下文。也就是说,在调用GrB_finalize()后,不允许随后调用GrB_init()。


2.5.2 多线程执行

GraphBLAS C API设计用于使用在共享地址空间内执行多个线程的应用程序。本规范未定义线程的创建、管理和同步方式。我们希望主机编程环境能够提供这些服务。

GraphBLAS的一致实现必须是线程安全的。当来自无竞争程序中多个线程的独立方法调用(即,GraphBLAS对象在方法调用之间不共享)返回的结果与其以某种交错顺序连续执行的结果相同时,GraphPLAS库是线程安全的。这是软件库中的常见需求。

线程安全适用于多个独立线程的行为。在多线程的更一般情况下,线程不是独立的;它们共享变量,并跨线程混合对这些变量的读写操作。内存一致性模型定义在读取两个或多个线程之间共享的对象时可以返回哪些值。GraphBLAS规范没有定义自己的内存一致性模型。相反,该规范定义了调用GraphBLAS方法的程序员和GraphBLAS库的实现者必须执行的操作,以便GraphBLAS规范的实现可以与主机环境的内存一致性模型正确配合。

内存一致性模型是根据不同线程中方法之间的先发生后关系定义的。定义案例是一个方法,该方法写入一个线程上的对象,该对象在另一个线程的GraphBLAS方法中读取(即用作IN或INOUT参数)。不同线程之间必须执行以下步骤。

  • 一系列GraphBLAS方法会导致GraphBLAS对象的定义。
  • 通过使用GrB_COMPLETE参数调用GrB_wait(),GraphBLAS对象进入完成状态(参见表3.1(b))。当GraphBLAS对象可以安全地用作来自不同线程的GraphBLAS方法调用中的IN或INOUT参数时,称其为完整。
  • 完成发生在至少以释放内存顺序执行的同步with关系之前。
  • 另一个线程上的synchronized with关系至少以获取内存顺序执行。
  • 此与关系同步发生在读取GraphBLAS对象的GraphBLAS方法之前。

我们至少在谈论内存顺序时使用这个短语,以表示可以使用更强的内存顺序(如顺序一致性)来代替获取释放顺序。

违反这些规则的程序包含数据竞赛。也就是说,它的读取和写入是跨线程无序的,使得变量的最终值未定义。包含数据竞赛的程序无效,并且该程序的结果未定义。我们注意到,多线程执行与阻塞和非阻塞执行模式都兼容。

完成是允许在线程之间的关系发生之前使用GraphBLAS对象的中心概念。在GraphBLAS(1.X)的早期版本中,任何从GraphBLAS对象生成非不透明值的操作都意味着完成。表2.2总结了这些操作)。在GraphBLAS 2.0中,这些方法不再意味着完成。之所以进行此更改,是因为在某些情况下需要非不透明值,但计算该值的对象不需要。我们希望GraphBLAS的实现能够利用这种情况,并且在不需要该对象时不会形成不透明对象。


 2.6 错误模型

所有GraphBLAS方法都返回 GrB_Info(枚举)类型的值,以便在方法返回时向系统提供可用的信息。返回值将是表3.13中所示的定义值之一。返回值分为三组:信息错误、API错误执行错误。虽然API和执行错误采用负值,但表3.13(a)中列出的信息返回值是非负值,包括GrB_SUCCESS(值为0)和 GrB_NO_value

API错误(在表3.13(b)中列出)意味着调用GraphBLAS方法时使用的参数违反了该方法的规则。这些错误仅限于通过检查GraphBLAS对象的维度和域、GraphBLAS运算符或调用方法时固定的标量参数值来确定的错误。API错误是确定性的,并且在平台和实现之间是一致的。即使在非阻塞模式下,API错误也不会延迟。也就是说,如果方法的调用方式会生成API错误,那么它总是返回相应的API错误值。如果GraphBLAS方法返回API错误,则可以保证该方法的任何参数(或任何其他程序数据)都未被修改。信息返回值 GrB_NO_value 也是确定性的,在非阻塞模式下从不延迟。

执行错误(在表3.13(c)中列出)表明在合法GraphBLAS方法调用的执行过程中出现了错误。它们的出现可能取决于执行环境的具体情况和被操作的数据值。这并不意味着执行错误是GraphBLAS实现的错误。例如,内存泄漏可能是由于应用程序源代码中的错误(“程序错误”)引起的,但它可能会在程序执行的不同点(或根本没有)表现出来,具体取决于平台、问题大小或当时正在运行的其他内容。例如,索引越界错误总是表示程序错误。

如果GraphBLAS方法返回 GrB_PANIC 以外的任何执行错误,则可以保证仅用作输入的任何参数的状态未被修改。输出参数可能处于无效状态,在程序流下游使用它们可能会导致其他错误。如果GraphBLAS方法返回 GrB_PANIC 执行错误,则无法保证任何程序数据的状态。

在非阻塞模式下,可以延迟执行错误。GrB_SUCCESS 的返回值只保证方法调用中没有API错误。如果输出对象obj处于非阻塞模式的方法返回执行错误值,则表示在obj上执行任何挂起操作期间发现错误,直到并包括完成这些挂起操作的 GrB_wait() 方法(第4.2.7节)调用。如果可能,该返回值将提供有关错误原因的信息。

如第4.2.7节所述,特定GraphBLAS对象obj上的 GrB_wait (obj) 完成该对象上的所有挂起操作。在调用 GrB_wait 之前,如果方法将obj作为OUT或INOUT参数,则不会报告其他错误。从GraphBLAS的角度来看,这些方法是完整的。有关调用 GrB_wait 后对象的保证状态的详细信息,请参阅第4.2.7节。

在调用任何修改不透明对象的GraphBLAS方法后,程序可以通过调用函数 GrB_error() 来检索额外的错误信息(超出该方法返回的错误代码),并按第4.2.8节所述传递该方法的输出对象。该函数返回一个指向以NULL结尾的字符串的指针,该字符串的内容依赖于实现。特别是,空字符串(不是空指针)始终是有效的错误字符串。GrB_error() 是一个线程安全函数,从这个意义上讲,多个线程可以同时调用它,每个线程都会返回自己的错误字符串,引用作为输入参数传递的对象。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值