-
Notifications
You must be signed in to change notification settings - Fork 15
/
tensor_algebra_cpu_phi.F90
150 lines (140 loc) · 6.09 KB
/
tensor_algebra_cpu_phi.F90
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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
!Tensor Algebra Library for Intel MIC built upon
!the Tensor Algebra Library for multi-core CPU.
!AUTHOR: Dmitry I. Lyakh (Liakh): [email protected]
!REVISION: 2018/07/24
!Copyright (C) 2014-2022 Dmitry I. Lyakh (Liakh)
!Copyright (C) 2014-2022 Oak Ridge National Laboratory (UT-Battelle)
!LICENSE: BSD 3-Clause
!NOTES:
! # This library is not thread-safe. All functions of this library are
! supposed to be called by the same single thread (due to the way
! the task handle management is implemented).
!PREPROCESSOR:
! -D NO_OMP: Disable OpenMP;
! -D NO_PHI: Ignore Intel MIC;
module tensor_algebra_cpu_phi
use tensor_algebra_cpu !certain procedures and globals are imported from this module
#ifndef NO_OMP
use omp_lib
#endif
implicit none
public
#ifndef NO_PHI
!PARAMETERS:
integer, parameter, public:: PHI_ALLOC_FREE=0
integer, parameter, public:: PHI_ALLOC_KEEP=1
integer, parameter, public:: PHI_REUSE_FREE=2
integer, parameter, public:: PHI_REUSE_KEEP=3
!DIR$ ATTRIBUTES OFFLOAD:mic:: PHI_ALLOC_FREE,PHI_ALLOC_KEEP,PHI_REUSE_FREE,PHI_REUSE_KEEP
!DIR$ ATTRIBUTES ALIGN:128:: PHI_ALLOC_FREE,PHI_ALLOC_KEEP,PHI_REUSE_FREE,PHI_REUSE_KEEP
integer, parameter, private:: phi_max_tasks=1024
!DERIVED TYPES:
!DATA:
integer, private:: j_,phi_task_ffe=1
integer, private:: phi_task_handles(1:phi_max_tasks)=(/(j_,j_=1,phi_max_tasks)/)
!FUNCTIONS:
private phi_get_task_handle
private phi_free_task_handle
public phi_init_task_handles
public phi_data_ctrl_clean
public phi_data_ctrl_set
public phi_tensor_block_copy_
contains
!--------------------------------------------------------
integer function phi_get_task_handle(task_handle) !SERIAL: Host
!Obtains a free task handle.
implicit none
integer, intent(out):: task_handle
if(phi_task_ffe.gt.0) then
if(phi_task_ffe.le.phi_max_tasks) then
task_handle=phi_task_handles(phi_task_ffe); phi_task_ffe=phi_task_ffe+1
phi_get_task_handle=0
else !no free handles left
phi_get_task_handle=1
endif
else !invalid phi_task_ffe
phi_get_task_handle=-1
endif
return
end function phi_get_task_handle
!---------------------------------------------------------
integer function phi_free_task_handle(task_handle) !SERIAL: Host
!Returns a task handle back to the free storage.
implicit none
integer, intent(inout):: task_handle
if(task_handle.gt.0.and.task_handle.le.phi_max_tasks) then
if(phi_task_ffe.gt.1.and.phi_task_ffe.le.phi_max_tasks+1) then
phi_task_ffe=phi_task_ffe-1; phi_task_handles(phi_task_ffe)=task_handle
task_handle=0; phi_free_task_handle=0
else !invalid phi_task_ffe
phi_free_task_handle=-1
endif
else !invalid task handle passed
phi_free_task_handle=-2
endif
return
end function phi_free_task_handle
!------------------------------------------
subroutine phi_init_task_handles() !SERIAL: Host
!Reinitializes task handle manager.
implicit none
integer i
do i=1,phi_max_tasks; phi_task_handles(i)=i; enddo
phi_task_ffe=1
return
end subroutine phi_init_task_handles
!------------------------------------------------
subroutine phi_data_ctrl_clean(data_ctrl) !SERIAL: Host
!Cleans data residence control flags.
implicit none
integer, intent(out):: data_ctrl
data_ctrl=0
return
end subroutine phi_data_ctrl_clean
!-----------------------------------------------------------------
integer function phi_data_ctrl_set(data_ctrl,arg_num,flag) !SERIAL:Host
!Sets data residence control flag <flag> for argument #<arg_num>.
implicit none
integer, intent(inout):: data_ctrl !data residence control flags
integer, intent(in):: arg_num !argument number: [0:max_tensor_operands-1]: 0 is always the destination tensor
integer, intent(in):: flag !flag to set: {PHI_ALLOC_FREE, PHI_ALLOC_KEEP, PHI_REUSE_FREE, PHI_REUSE_KEEP}
phi_data_ctrl_set=0
if(arg_num.ge.0.and.arg_num.lt.max_tensor_operands) then
select case(flag)
case(PHI_ALLOC_FREE)
data_ctrl=ibclr(data_ctrl,arg_num*2+1)
data_ctrl=ibclr(data_ctrl,arg_num*2)
case(PHI_ALLOC_KEEP)
data_ctrl=ibclr(data_ctrl,arg_num*2+1)
data_ctrl=ibset(data_ctrl,arg_num*2)
case(PHI_REUSE_FREE)
data_ctrl=ibset(data_ctrl,arg_num*2+1)
data_ctrl=ibclr(data_ctrl,arg_num*2)
case(PHI_REUSE_KEEP)
data_ctrl=ibset(data_ctrl,arg_num*2+1)
data_ctrl=ibset(data_ctrl,arg_num*2)
case default
phi_data_ctrl_set=-1
end select
else
phi_data_ctrl_set=-2
endif
return
end function phi_data_ctrl_set
!----------------------------------------------------------------------------------------------------
integer function phi_tensor_block_copy_(mic_num,data_ctrl,tens_in,tens_out,phi_handle,transp) !Paralell: Host+MIC
!This function schedules an asynchronous tensor block copy/transpose on MIC device #<mic_num>.
implicit none
integer, intent(in):: mic_num !MIC device number: [0..max]
integer, intent(in):: data_ctrl !data reuse flags for all tensor arguments
type(tensor_block_t), intent(in):: tens_in !input tensor block (arg#1)
type(tensor_block_t), intent(inout):: tens_out !output tensor block (arg#0)
integer, intent(out):: phi_handle !task handle (for further queries)
integer, intent(in), optional:: transp(0:*) !permutation (0:sign; 1..:permutation_O2N)
integer i,j,k,l,m,n
phi_tensor_block_copy_=0; n=tens_in%tensor_shape%num_dim
i=phi_get_task_handle(phi_handle); if(i.ne.0) then; phi_tensor_block_copy_=1; return; endif
return
end function phi_tensor_block_copy_
#endif
end module tensor_algebra_cpu_phi