1#ifndef STAN_MATH_GPU_KERNELS_TRIDIAGONALIZATION_HPP
2#define STAN_MATH_GPU_KERNELS_TRIDIAGONALIZATION_HPP
10namespace opencl_kernels {
13static constexpr const char* tridiagonalization_householder_kernel_code
28 __global
double* P, __global
double* V, __global
double* q_glob,
29 const int P_rows,
const int V_rows,
const int j,
const int k) {
30 const int lid = get_local_id(0);
31 const int gid = get_global_id(0);
32 const int gsize = get_global_size(0);
33 const int lsize = get_local_size(0);
34 const int ngroups = get_num_groups(0);
35 const int wgid = get_group_id(0);
39 const int P_start = P_rows * (k + j) + k + j;
40 const int P_span = P_rows * (k + j + 1) - P_start;
41 for (
int i = lid; i < P_span; i += lsize) {
45 for (
int l = 0; l < j; l++) {
46 acc += P[P_rows * (k + l) + k + j + i] * V[V_rows * l + j - 1]
47 + V[V_rows * l + j - 1 + i] * P[P_rows * (k + l) + k + j];
49 double tmp = P[P_start + i] - acc;
56 __local
double q_local[LOCAL_SIZE_];
60 barrier(CLK_LOCAL_MEM_FENCE | CLK_GLOBAL_MEM_FENCE);
61 for (
int step = lsize / REDUCTION_STEP_SIZE;
step > 0;
62 step /= REDUCTION_STEP_SIZE) {
64 for (
int i = 1; i < REDUCTION_STEP_SIZE; i++) {
65 q_local[lid] += q_local[lid +
step * i];
68 barrier(CLK_LOCAL_MEM_FENCE);
74 double p1 = P[P_start + 1];
76 alpha = -copysign(
sqrt(q), P[P_start]);
86 barrier(CLK_LOCAL_MEM_FENCE);
90 double multi = M_SQRT2 / q;
92 for (
int i = lid + 1; i < P_span; i += lsize) {
93 P[P_start + i] *= multi;
97 P[P_rows * (k + j + 1) + k + j]
98 = P[P_rows * (k + j) + k + j + 1] * q / M_SQRT2 + alpha;
104static constexpr const char* tridiagonalization_v_step_1_kernel_code
122 const __global
double* P,
const __global
double* V,
123 __global
double* Uu, __global
double* Vu,
const int P_rows,
124 const int V_rows,
const int k) {
125 const int lid = get_local_id(0);
126 const int gid = get_global_id(0);
127 const int gsize = get_global_size(0);
128 const int lsize = get_local_size(0);
129 const int ngroups = get_num_groups(0);
130 const int wgid = get_group_id(0);
132 __local
double res_loc1[LOCAL_SIZE_];
133 __local
double res_loc2[LOCAL_SIZE_];
137 const __global
double* vec
138 = P + P_rows * (k + ngroups) + k + ngroups + 1;
139 const __global
double* M1 = P + P_rows * (k + wgid) + k + ngroups + 1;
140 const __global
double* M2 = V + V_rows * wgid + ngroups;
141 for (
int i = lid; i < P_rows - k - ngroups - 1;
148 res_loc1[lid] = acc1;
149 res_loc2[lid] = acc2;
150 barrier(CLK_LOCAL_MEM_FENCE);
152 for (
int step = lsize / REDUCTION_STEP_SIZE;
step > 0;
153 step /= REDUCTION_STEP_SIZE) {
155 for (
int i = 1; i < REDUCTION_STEP_SIZE; i++) {
156 res_loc1[lid] += res_loc1[lid +
step * i];
157 res_loc2[lid] += res_loc2[lid +
step * i];
160 barrier(CLK_LOCAL_MEM_FENCE);
163 Uu[wgid] = res_loc1[0];
164 Vu[wgid] = res_loc2[0];
170static constexpr const char* tridiagonalization_v_step_2_kernel_code
190 const __global
double* P, __global
double* V,
191 const __global
double* Uu,
const __global
double* Vu,
192 const int P_rows,
const int V_rows,
const int k,
const int j) {
193 const int lid = get_local_id(0);
194 const int gid = get_global_id(0);
195 const int gsize = get_global_size(0);
196 const int lsize = get_local_size(0);
197 const int ngroups = get_num_groups(0);
198 const int wgid = get_group_id(0);
200 int work = P_rows - k - j - 1;
203 const __global
double* vec = P + P_rows * (k + j) + k + j + 1;
204 const __global
double* M1 = P + P_rows * (k + j + 1) + k + j + 1;
205 const __global
double* M2 = P + P_rows * k + k + j + 1;
206 const __global
double* M3 = V + j;
209 for (i = 0; i <= gid; i++) {
210 acc += M1[P_rows * i + gid] * vec[i];
212 for (
int i = 0; i < j; i++) {
213 acc -= M2[P_rows * i + gid] * Vu[i];
214 acc -= M3[V_rows * i + gid] * Uu[i];
216 V[V_rows * j + gid + j] = acc;
219 = (float)work / ngroups;
220 int start = work_per_group * wgid;
221 int end = work_per_group * (wgid + 1);
222 __local
double res_loc[LOCAL_SIZE_];
223 for (
int i = start; i < end; i += 1) {
225 for (
int l = i + 1 + lid; l < work; l += LOCAL_SIZE_) {
226 acc += M1[P_rows * i + l] * vec[l];
229 barrier(CLK_LOCAL_MEM_FENCE);
230 for (
int step = lsize / REDUCTION_STEP_SIZE;
step > 0;
231 step /= REDUCTION_STEP_SIZE) {
233 for (
int i = 1; i < REDUCTION_STEP_SIZE; i++) {
234 res_loc[lid] += res_loc[lid +
step * i];
237 barrier(CLK_LOCAL_MEM_FENCE);
240 V[V_rows * (j + 1) + i + j] = res_loc[lid];
242 barrier(CLK_LOCAL_MEM_FENCE);
248static constexpr const char* tridiagonalization_v_step_3_kernel_code
263 __global
double* P, __global
double* V, __global
double* q,
264 const int P_rows,
const int V_rows,
const int k,
const int j) {
265 const int lid = get_local_id(0);
266 const int gid = get_global_id(0);
267 const int gsize = get_global_size(0);
268 const int lsize = get_local_size(0);
269 const int ngroups = get_num_groups(0);
270 const int wgid = get_group_id(0);
272 __global
double* u = P + P_rows * (k + j) + k + j + 1;
273 __global
double* v = V + V_rows * j + j;
276 for (
int i = lid; i < P_rows - k - j - 1; i += LOCAL_SIZE_) {
277 double vi = v[i] + v[i + V_rows];
281 __local
double res_loc[LOCAL_SIZE_];
283 barrier(CLK_LOCAL_MEM_FENCE);
284 for (
int step = lsize / REDUCTION_STEP_SIZE;
step > 0;
285 step /= REDUCTION_STEP_SIZE) {
287 for (
int i = 1; i < REDUCTION_STEP_SIZE; i++) {
288 res_loc[lid] += res_loc[lid +
step * i];
291 barrier(CLK_LOCAL_MEM_FENCE);
293 acc = res_loc[0] * 0.5;
294 for (
int i = lid; i < P_rows - k - j - 1; i += LOCAL_SIZE_) {
298 P[P_rows * (k + j + 1) + k + j] -= *q / M_SQRT2 * u[0];
303const kernel_cl<in_out_buffer, in_out_buffer, out_buffer, int, int, int, int>
305 {tridiagonalization_householder_kernel_code},
306 {{
"REDUCTION_STEP_SIZE", 4},
307 {
"LOCAL_SIZE_", 1024}});
309const kernel_cl<in_buffer, in_buffer, out_buffer, out_buffer, int, int, int>
311 {tridiagonalization_v_step_1_kernel_code},
312 {{
"REDUCTION_STEP_SIZE", 4},
313 {
"LOCAL_SIZE_", 64}});
315const kernel_cl<in_buffer, out_buffer, in_buffer, in_buffer, int, int, int, int>
317 {tridiagonalization_v_step_2_kernel_code},
318 {{
"REDUCTION_STEP_SIZE", 4},
319 {
"LOCAL_SIZE_", 64}});
321const kernel_cl<in_out_buffer, in_out_buffer, out_buffer, int, int, int, int>
323 {tridiagonalization_v_step_3_kernel_code},
324 {{
"REDUCTION_STEP_SIZE", 4},
325 {
"LOCAL_SIZE_", 1024}});
const kernel_cl< in_buffer, in_buffer, out_buffer, out_buffer, int, int, int > tridiagonalization_v_step_1("tridiagonalization_v_step_1", {tridiagonalization_v_step_1_kernel_code}, {{"REDUCTION_STEP_SIZE", 4}, {"LOCAL_SIZE_", 64}})
const kernel_cl< in_buffer, out_buffer, in_buffer, in_buffer, int, int, int, int > tridiagonalization_v_step_2("tridiagonalization_v_step_2", {tridiagonalization_v_step_2_kernel_code}, {{"REDUCTION_STEP_SIZE", 4}, {"LOCAL_SIZE_", 64}})
const kernel_cl< in_out_buffer, in_out_buffer, out_buffer, int, int, int, int > tridiagonalization_v_step_3("tridiagonalization_v_step_3", {tridiagonalization_v_step_3_kernel_code}, {{"REDUCTION_STEP_SIZE", 4}, {"LOCAL_SIZE_", 1024}})
const kernel_cl< in_out_buffer, in_out_buffer, out_buffer, int, int, int, int > tridiagonalization_householder("tridiagonalization_householder", {tridiagonalization_householder_kernel_code}, {{"REDUCTION_STEP_SIZE", 4}, {"LOCAL_SIZE_", 1024}})
T step(const T &y)
The step, or Heaviside, function.
fvar< T > sqrt(const fvar< T > &x)
The lgamma implementation in stan-math is based on either the reentrant safe lgamma_r implementation ...