浅谈并行编程语言 Unified Parallel C(4)

共享和私有数据

UPC 将数据分为私有和共享两种类型。UPC 对 C 语言扩展了一个新的数据类型限定词 shared.类型限定词 shared声明数据为共享类型。如果数据声明中没有用到 shared数据类型限定词,则所声明的数据位私有数据。可以说在 C 语言中的数据类型在 UPC 中都是私有数据类型。

当声明一个共享数据类型的时候,该数据会被分配到共享内存空间中。若该共享数据是标量数据,则该数据会被分配到线程 0 的共享内存空间中。若该共享数据为数组,则该数据将根据该数组中的布局限定词来分配到共享内存空间中,关于共享限定词,将在 4.2 中详细阐述。若该当你声明一个私有数据类型的时候,该数据会被分配到每一个线程的私有内存空间中。


清单 1. 数据声明例子
int x; // 声明了一个私有数据类型 shared int y; // 声明了一个共享整型数据 shared int z[11] // 声明了一个共享整型类型数组 , 数组中包含 11 个共享整型类型元素 图 2 显示了以上所声明的数据在内存中的视图  


图 2. 数据声明内存视图

图 2. 数据声明内存视图


如图 2 所示声明语句“int x;”声明了一个私有整型数据,这个数据被分配到每一个线程的私有空间中。声明语句“shared int y”声明了一个共享整型数据,这个数据被分配到线程 0 的共享内存空间中。声明语句“shared int z[11]”声明了一个共享整型数组,该数组的元素如图依次被分配到每一个线程的共享内存空间。

数组

UPC 的数组声明引入了一个布局类型限定词。布局类型限定词决定多少个连续的共享元素被分配到同一个线程的共享内存空间中。例如 , 下面的声明了一个共享浮点型的数组 A:

shared [block_size] int A[number_of_elements]

[block_size] 是布局类型限定词,block_size 是一个非负的数值,代表区块的大小。例如,当布局类型限定词是 [3] 时,则每三个连续的元素为一个区块分配到一个线程的共享内存空间中。假若局类型限定词是下列的情形,区块大小有所不同:

如果布局类型限定词不存在的情况下,则所声明的共享数组按照区块大小为 1 进行分配。 如果布局类型限定词为 [ ] 或者 [0], 说明区块大小为无穷大,则所声明的共享数组将所有元素分配到线程 0 的共享内存空间中。 如果布局类型限定词为 [*], 则所声明的共享数组将按照区块大小为 ( sizeof(array) / upc_elemsizeof(array) + THREADS - 1 ) / THREADS 进行分配。
清单 2. 数组声明例子
int A[3]; // 声明了一个私有整型数组 A,有 3 个元素。 shared float B[5] // 声明一个共享浮点型数组 B,有 5 个元素,按照区块大小为 1 进行分配。 shared [2] int C[11] // 声明一个共享整型数组 C, 有 11 个元素,按照区块大小为 3 进行分配 shared [] float D[5] // 声明一个共享浮点型数组 D, 有 5 个元素,所有元素分配到线程 0 的共享内存空间中。  

以上的例子中所声明的数组元素在内存中的分配视图下面图 3 所示。


图 3. 数组元素内存分配视图

图 3. 数组元素内存分配视图


如图 3 所示,语句“int A[3]; ”声明了一个私有整型数组 A,每一个线程都被分配了相同的数组元素。语句“shared float B[5]; ”声明一个共享浮点型数组 B,因为没有布局类型限定词,所有默认按照区块大小为 1 进行元素的一次分配。语句“shared [2] int C[11]”声明了一个共享整型数组 C,区块大小为 2,即每 2 个连续的元素会被一次分配到每个线程之中,直至元素分配完毕为止。语句“shared [] float D[5]”声明了一个共享浮点型数组 D,区块大小为无穷大,D 数组的所有元素全被分配到线程 0 的共享内存空间中。

指针

因为 UPC 中具有共享和私有两种数据类型,所以一个指针所指向的数据可能是共享或者私有数据类型,并且指针的本身可能是共享或者私有数据类型,因此 UPC 中共有 4 种指针类型如下面图 4 所示。红色箭头代表的是 指向共享数据共享指针,黑色箭头代表的是 指向私有数据共享指针,蓝色箭头代表的是 指向共享数据私有指针,绿色箭头代表的是 指向私有数据私有指针。


图 4. UPC 四种指针种类

图 4. UPC 四种指针种类


UPC 的四种指针在内存中的视图如下面图 5 所示。


图 5. UPC 指针内存视图

图 5. UPC 指针内存视图


p1 是指向私有数据私有指针。所有 C 语言中的指针都是这种类型指针,特点是速度快。如果一个指向共享数据指针和所指的数据有亲缘关系,您可以将该指针转化为 p1 类型指针来提高访问速度。 p2 是指向共享数据私有指针。这个指针可以用来访问共享数据。p2 速度要比 p1 慢。p2 访问和它有亲缘关系的共享数据速度比访问和它没有亲缘关系的共享数据的速度快。 p3 是指向私有数据共享指针。这种指针会是线程访问其他线程的私有数据,不建议使用。 p4 是指向共享数据共享指针。
清单 3. 指向私有数据私有指针声明
int *p1; // 声明了一个指向私有整型数据的私有指针。这个指针将被分配到每一个线程的私有内存中 shared int *p2 // 声明一个指向共享数据私有指针,这个指针将被分配到每一个线程的私有内存中 int * shared p3// 声明一个指向私有数据共享指针,不建议使用,这个指针被分配到线程 0 的共享内存中 shared int * shared p4// 声明了一个指向共享数据共享指针,这个指针被分配到线程 0 的共享内存中  

操作符

UPC 在 C 的基础上扩展了以下的 5 个一元运算符。这些运算符的操作数可以是一个类型或者是一元表达式。

& 返回指向某一个操作数的指针。如果这个操作数是一个 T 类型的共享数据,则返回值具有 shared [] *T 的类型。 sizeof 返回一个操作数字节大小。 upc_blocksizeof 返回一个操作数的区块大小,这个值即是在类型声明中的布局类型限定词中的值。 upc_elemsizeof 返回非数组的最左边类型的字节大小。 upc_localsizeof 返回一个共享类型或者共享数据内和当前执行的线程有亲缘关系的字节大小。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wwsgsg.html