关于 Unified Parallel C 中的指针4
 
- UID
- 1066743
|

关于 Unified Parallel C 中的指针4
清单 10. 指向共享数据指针算法示例 51
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
| # include <stdio.h> // 假定程序由 3 个线程来运行
# include <upc.h>
# define N 8
shared[] int *shared p1;
shared[] int *p2;
void main()
{
int i=0;
if(MYTHREAD == 1)
p1=upc_alloc(N*sizeof(int));
upc_barrier;
upc_forall(i=0;i<N;i++;i)
p1=i;
upc_barrier;
p2=p1+MYTHREAD;
upc_barrier;
printf("Th:%d,*p1=%d,*p2=%d\n",MYTHREAD,*p1,*p2);
printf("phaseof(p2)=%d,threadof(p2)=%d\n",upc_phaseof(p2),upc_threadof(p2));
}
|
图 19. 清单 10 内存视图 图 20. 清单 10 程序输出 指针类型转换,UPC 语言中的指针相互转换可以分为下面四种类型:
- 指向共享数据指针转换为指向共享数据指针
- 指向共享数据指针转换为指向私有数据指针
- 指向私有数据指针转换为指向共享数据指针
- 指向私有数据指针转换为指向私有数据指针
指向共享数据指针转换为指向共享数据指针如果两个指向共享数据指针具有不同的类型大小或者区块大小,那么结果指针的相位为 0.
清单 11.具有不同区块大小的指向共享数据指针之间的转换1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
| # include <upc.h> // 假定程序由 4 个线程来运行
# include <stdio.h>
# define FAILURE 1
# define SUCCESS 0
# define BLKSIZE 3
# define ARRSIZE 60
# define verify(result,expect) \
{ if ((result)!=(expect)) \
{ \printf("Error: fail at line %d: mythread=%d, result= %d, expect= %d\n",
__LINE__, MYTHREAD, result,expect); \
upc_global_exit(FAILURE); \
} \
}
shared int *p1,arr2[ARRSIZE];
shared[BLKSIZE] int *p2,arr1[ARRSIZE];
int main()
{
int i;
/* initialize array */
upc_forall(i=0;i<ARRSIZE;i++;i)
{
arr1=i;
arr2=-i;
}
upc_barrier;
/* 案例 1:将一个数据分布区块大小为 3 的指向共享数据指针,转换为一个数据分布区块大小为 1 的指向共享数据指针 */
/*p1 是一个数据分布区块大小为 1 的指向共享数据指针,arr1 是一个数据分布区块大小为 3 的共享数组。
当把数组元素 arr1[5] 的地址赋给指针 p1,涉及到把一个数据分布区块大小为 3 的指向共享数据指针转换
为一个数据分布区块大小为 1 的指向共享数据指针如下面所进行的转换 :
p1=(shared int *)&arr1[5];
可以通过下面的步骤来辨别出在转换之后,p1 指针指向的是哪个数组元素。
第一步:先将数组 arr1 展开,再将指针 p1 展开 .
第二步:找到 p1 指针布局中与数组 arr1 中数组元素 arr1[5] 相同的位置。
(所谓相同的位置,即是所在的线程相同,偏移量也相同)。
第三步:判断在 p1 的展开布局之中,与数组 arr1 中 arr1[5] 相同的位置的相位。
如果该相位为 0,那么在转换之后,p1 仍旧指向数组元素 arr1[5] 所在的位置。
如果该位置的相位不为 0,指针将指向该数据区块中相位为 0 的位置。
(注意:当两个具有不同数据分布区块大小的指向共享数据指针相互转换的时候,结果指针的相位恒为 0.)
*/
/* 下面我们先将数组 arr1 展开。数组 arr1 是数据分布区块大小为 3 的共享数组
线程 0 线程 1 线程 2 线程 3
0 3 6 9
1 4 7 10
2 5 8 11 // arr1[5] 元素对应的线程为 1,相位为 2,值为 5
12 15 18 21
13 16 19 22
14 17 20 23
....
57 58 59 60
*/
/* 下面再将 p1 指针展开,p1 是一个数据分布区块大小为 1,指向共享数据的指针。
找到与上面 arr1 数组中数组元素 arr1[5] 相同的位置(即相同的线程,相同的偏移量),
那么是位置 9,因为 p1 的区块大小为 1,位置 9 对应的相位为 0,所以 p1 在转换之后将仍然指向位置 9,
即数组元素 arr1[5] 所在的位置。
线程 0 线程 1 线程 2 线程 3
0 1 2 3
4 5 6 7
8 9 10 11
12 13 14 15
16 17 18 19
20 21 22 23
....
*/
p1=(shared int *)&arr1[5]; /*p1 是数据分布区块大小为 1 的指针,
而数组 arr1 是数据分布区块大小为 3 的数组,不匹配,所以会涉及强制转换
*/
verify(upc_phaseof(p1),0); // 验证 p1 在转换之后的相位一定为 0
verify(upc_threadof(p1),upc_threadof(&arr1[5])); //p1 转换之后,所在的线程不变
verify(*p1,5); // 验证 p1 在转换后仍然指向数组元素 arr1[5]
verify(*(p1-2),10); // 将 p1 向后移动 2 个元素位置,将指向数组元素 arr1[10].
verify(*(p1+2),11); // 将 p1 指针向前移动 2 个元素位置,p1 将指向数组元素 arr1[11].
/* 案例 2:将一个数据分布区块大小为 1 的指向共享数据指针转换为数据分布区块大小为 3 的指向共享数据在指针 */
/* 数组 arr2 是一个数据分布区块大小为 1 的共享数组。将数组 arr2 展开如下:
线程 0 线程 1 线程 2 线程 3
0 1 2 3
4 5 6 7 // 数组元素 arr2[5] 对应线程 1, 相位为 0
8 9 10 11
12 13 14 15
16 17 18 19
20 21 22 23
. . .
57 58 59 60
*/
/*p2 是一个数据分布区块大小为 3 的指针,将其展开如下。对应于数组 arr2 中数组元素 arr2[5] 的位置在 p2 中为位置 4。
位置 4 和数组元素 arr2[5] 对应相同的线程,偏移量也相同。但是位置 4 的相位为 1,在这种情况下,
指针将指向同一区块中相位为 0 的位置,即位置 3. 对应的数组元素为 arr2[1]。所以 p2 在转换之后,将指向数组元素 arr2[1]。
线程 0 线程 1 线程 2 线程 3
0 3 6 9
1 4 7 10
2 5 8 11
12 15 18 21
13 16 19 22
14 17 20 23
. . .
*/
p2=(shared[BLKSIZE] int *)&arr2[5];
verify(*p2,-1); // 验证 p2 在强制转换之后指向元素 arr2[1]
verify(upc_phaseof(p2),0); // p2 在强制转换后相位变为 0
verify(upc_threadof(p2),upc_threadof(&arr2[5])); // 强制转换后,p2 所在的线程不变
verify(*(++p2),-5); // 将 p2 指针向前移动 2 个位置,将指向数组元素 arr2[5]
verify(*(p2-2),-8); // 将 p2 指针向后移动 2 个位置,将会指向元素 arr2[8]
return SUCCESS;
}
|
|
|
|
|
|
|