首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

关于 Unified Parallel C 中的指针2

关于 Unified Parallel C 中的指针2

指向共享数据共享类型指针如图 1 中的 p4, 是一个指向共享数据的共享类型指针。当声明该指针时,UPC 语言会在线程 0 中为该指针分配内存。该类型指针可以被任何线程使用来访问共享数据。例如,下面的语句声明了一个指向共享数据共享类型指针。
1
shared int *shared p4;




清单 4. 指向共享数据共享类型指针
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# include <upc.h> // 假定由 2 个线程运行该程序
# include <stdio.h>

shared int *shared p4[THREADS]; // 声明一个共享指针数组
shared int a[THREADS]; // 声明了一个共享数组

void main()
{
a[MYTHREAD]=MYTHREAD+99;
if(MYTHREAD == 0)
  p4[MYTHREAD]=&a[1];
else
   p4[MYTHREAD]=&a[0];
upc_barrier;

printf("Th=%d,*p4[%d]=%d\n",MYTHREAD,MYTHREAD,*p4[MYTHREAD]);
}




图 8. 清单 4 程序内存视图图 9. 清单 4 程序输出指向共享数据指针算法指向私有数据私有指针的算法可以参见 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. 指向共享数据指针算法示例 1
1
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. 指向共享数据指针算法示例 2
1
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. 指向共享数据指针算法示例 3
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
# 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. 指向共享数据指针示例 4
1
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 程序输出清单 10. 指向共享数据指针算法示例 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
# 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 程序输出
返回列表