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

关于 Unified Parallel C 中的指针3
指向共享数据指针算法指向私有数据私有指针的算法可以参见 C 语言中的指针算法,在此不作赘述。此处着重讨论指向共享数据的指针算法。指向共享数据指针包含下面两条信息:
- 该指针所在的线程
- 用来计算该指针在线程内相位(phase) 的偏移量。所谓相位,即在一个数据区块中的位置。例如一个区块大小为 3,那么排在区块中第一个数据的相位为 0,第二个数据相位为 1,第三个数据的相位为 2
如果一个指向共享数据指针的数据分布区块大小为无穷大时候,指针做加运算的时候与 C 语言中的指针相似。在加运算后,指针所在的线程保持不变,而该指针的相位恒为 0.
如果一个指向共享数据的指针数据分布区块大小为一个有限的值,指针在做加运算的时候,根据数组元素的顺序来移动。在加运算之后,指针所在的线程和该指针的相位可能会改变。
清单 5. 指向共享数据指针算法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
| # include <upc.h> // 假定由 3 个线程来运行该程序
# include <stdio.h>
# define B 3
# define N 20
shared [B] int arr[N];
shared [B] int *p, *p1;
void main()
{
int i;
upc_forall(i=0;i<N;i++;&arr)
{
arr=i;
}
upc_barrier;
p=&arr[0]; // 指针 p 指向数组元素 arr[0]
p1=p+5; // 执行此语句之后,指针 p1 将指向数组元素 arr[5]
printf("1-Th=%d,*p=%d,Phaseof(p)=%d,Threadof(p)=%d\n",MYTHREAD,*p,upc_phaseof(p),
upc_threadof(p));
printf("2-Th=%d,*p1=%d,Phaseof(p1)=%d,Threadof(p1)=%d\n",MYTHREAD,*p1,
upc_phaseof(p1),upc_threadof(p1));
}
|
图 10. 清单 5 程序输出 经过赋值运算 p1=p+i 之后,在任何的 UPC 语言的实现中,下面两个等式恒成立:
1
2
| upc_phaseof(p1) == (upc_phaseof(p) + i) mod B
upc_threadof(p1) == (upc_threadof(p)+ (upc_phaseof(p) + i) div B) mod THREADS
|
注释:div 运算符表示整数运算,结果向负无穷方向归约。Mod 运算符表示返回非负的余数。
指向共享数据指针之间的比较只有两个指针都指向同一个数组,这种比较才有意义。
指向共享数据指针之间的减法运算只有存在一个整形类型 x 满足下面两个等式的情况下才有意义:
1
2
| pts1 + x == pts2
upc_phaseof (pts1 + x) == upc_phaseof (pts2)
|
等式中,pts1 与 pts2 是两个指向共享数据指针,两个指针相减(pts2-pts1) 的结果为 x, 这种情况下,该减法有意义。
指向共享数据指针与指向私有数据指针的任何两元运算(如减,比较运算等)都没有意义,因为这两种指针类型不匹配。
清单 6. 指向共享数据指针算法示例 11
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
| # include <upc.h> // 假定由 3 个线程运行该程序
# include <stdio.h>
# define N 8
shared[2] int a[N];
shared[2] int *p1,*p2;
void main()
{
int i=0;
upc_forall(i=0;i<N;i++;i)
a=i;
upc_barrier;
p1=&a[1];
p2=p1+MYTHREAD; // 注意 :p2-p1 所得的差必须与 MYTHREAD 的值相等
printf("Th:%d,*p1=%d,*p2=%d,p2-p1=%d\n",MYTHREAD,*p1,*p2,p2-p1);
}
|
图 11. 清单 6 程序内存视图 图 12. 清单 6 程序内存视图 清单 7. 指向共享数据指针算法示例 21
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| # include <upc.h> // 假定由 3 个线程来运行该程序
# include <stdio.h>
# define N 8
shared[2] int a[N];
shared[2] int *p1,*p2;
void main()
{
int i=0;
upc_forall(i=0;i<N;i++;i)
a=i;
upc_barrier;
p1=a+1+MYTHREAD;
p2=p1+MYTHREAD;
printf("Th:%d,*p1=%d,*p2=%d\n",MYTHREAD,*p1,*p2);
}
|
图 13. 清单 7 程序内存视图 图 14. 清单 7 程序输出 清单 8. 指向共享数据指针算法示例 31
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
| # include <upc.h> // 假定由 3 个线程来运行该程序
# include <stdio.h>
# define N 8
shared[2] int a[N];
shared[2] int *p1,*shared p2;
void main()
{
int i=0;
upc_forall(i=0;i<N;i++;i)
a=i;
upc_barrier;
p1=&a[1];
p2=&a[5];
upc_barrier;
p1++;
if(MYTHREAD == 0)
p2--;
upc_barrier;
printf("Th:%d,*p1=%d,*p2=%d\n",MYTHREAD,*p1,*p2);
printf("phase(p1)=%d,threadof(p1)=%d\n",upc_phaseof(p1),upc_threadof(p1));
printf("phase(p2)=%d,threadof(p2)=%d\n",upc_phaseof(p2),upc_threadof(p2));
}
|
图 15. 清单 8 程序内存视图 图 16. 清单 8 程序输出 清单 9. 指向共享数据指针示例 41
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
| # include <upc.h> // 假定由 3 个线程来运行该程序
# include <stdio.h>
# define N 8
shared[] int a[N];
shared[] int *p1,*shared p2;
void main()
{
int i=0;
upc_forall(i=0;i<N;i++;i)
a=i;
upc_barrier;
p1=&a[1];
if(MYTHREAD == THREADS -1)
p2=p1+5;
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));
}
|
图 17. 清单 9 程序内存视图 图 18. 清单 9 程序输出 |
|
|
|
|
|