16
16
from bfast .base import BFASTMonitorBase
17
17
from bfast .monitor .utils import compute_end_history , compute_lam , map_indices
18
18
19
+ # generated by Futhark
19
20
from .bfastfinal import bfastfinal
20
21
21
- #################################################
22
- # ## Remember to compile with, e.g.,
23
- # ## $ gpu-pyopencl --library bfastfuth.fut
24
- #################################################
22
+ ############################################################
23
+ # ## Remember to run:
24
+ # ## cd futhark
25
+ # ## make
26
+ # ## cp bfastfinal.py ../
27
+ ############################################################
25
28
26
29
class BFASTMonitorOpenCL (BFASTMonitorBase ):
27
-
28
30
""" Parallel BFASTMonitor implementation optimized for GPUs. The
29
31
interface follows the one of the corresponding R package,
30
32
see: https://cran.r-project.org/web/packages/bfast
@@ -67,7 +69,6 @@ class BFASTMonitorOpenCL(BFASTMonitorBase):
67
69
-----
68
70
69
71
"""
70
-
71
72
def __init__ (self ,
72
73
start_monitor ,
73
74
freq = 365 ,
@@ -82,20 +83,19 @@ def __init__(self,
82
83
platform_id = 0 ,
83
84
device_id = 0
84
85
):
85
-
86
86
k_valid = list (range (3 , 11 ))
87
87
88
88
if k not in k_valid :
89
89
raise Exception ("Current implementation can only handle the following values for k: {}" .format (k_valid ))
90
90
91
- super (BFASTMonitorOpenCL , self ).__init__ (start_monitor ,
92
- freq ,
93
- k = k ,
94
- hfrac = hfrac ,
95
- trend = trend ,
96
- level = level ,
97
- period = period ,
98
- verbose = verbose )
91
+ super ().__init__ (start_monitor ,
92
+ freq ,
93
+ k = k ,
94
+ hfrac = hfrac ,
95
+ trend = trend ,
96
+ level = level ,
97
+ period = period ,
98
+ verbose = verbose )
99
99
100
100
self .detailed_results = detailed_results
101
101
self .find_magnitudes = find_magnitudes
@@ -112,9 +112,7 @@ def __init__(self,
112
112
sizes = self ._get_futhark_params ())
113
113
114
114
def _init_device (self , platform_id , device_id ):
115
- """ Initializes the device.
116
- """
117
-
115
+ """ Initializes the device."""
118
116
try :
119
117
platforms = pyopencl .get_platforms ()
120
118
devices = platforms [platform_id ].get_devices ()
@@ -126,9 +124,7 @@ def _init_device(self, platform_id, device_id):
126
124
self .queue = pyopencl .CommandQueue (self .ctx )
127
125
128
126
def _print_device_info (self ):
129
- """ Prints information about the current device.
130
- """
131
-
127
+ """ Prints information about the current device. """
132
128
if self .verbose > 0 :
133
129
print ("=================================================================================" )
134
130
print ("Device id: " + str (self .device_id ))
@@ -227,6 +223,7 @@ def fit(self, data, dates, n_chunks=None, nan_value=0):
227
223
228
224
self .breaks = results ['breaks' ]
229
225
self .means = results ['means' ]
226
+ self .valids = results ['valids' ]
230
227
231
228
if self .find_magnitudes or self .detailed_results :
232
229
self .magnitudes = results ['magnitudes' ]
@@ -242,16 +239,13 @@ def get_timers(self):
242
239
dict : An array containing the runtimes
243
240
for the different phases.
244
241
"""
245
-
246
242
return self ._timers
247
243
248
244
def _fit_chunks (self , data , dates , n_chunks = 10 , nan_value = 0 ):
249
245
data_chunks = numpy .array_split (data , n_chunks , axis = 1 )
250
-
251
246
results = []
252
247
253
248
for chunk_idx in range (n_chunks ):
254
-
255
249
start_chunk = time .time ()
256
250
if self .verbose > 0 :
257
251
print ("Processing chunk index {}/{}" .format (chunk_idx + 1 , n_chunks ))
@@ -317,7 +311,7 @@ def _fit_single_preprocess(self, data, dates, nan_value):
317
311
print ("--- runtime for data transfer (host->device):\t {}" .format (end - start ))
318
312
319
313
start = time .time ()
320
- data_cl = self .futobj .remove_nans (nan_value , data_cl )
314
+ data_cl = self .futobj .convertToFloat (nan_value , data_cl )
321
315
y_cl = self .futobj .reshapeTransp (data_cl )
322
316
end = time .time ()
323
317
if self .verbose > 0 :
@@ -353,21 +347,24 @@ def _fit_single_kernel(self, y_cl, mapped_indices_cl):
353
347
self .lam ,
354
348
mapped_indices_cl , y_cl )
355
349
elif self .find_magnitudes :
356
- breaks , means , magnitudes = self .futobj .mainMagnitude (trend ,
357
- self .k ,
358
- self .n ,
359
- self .freq ,
360
- self .hfrac ,
361
- self .lam ,
362
- mapped_indices_cl , y_cl )
350
+ Ns , \
351
+ breaks , \
352
+ means , \
353
+ magnitudes = self .futobj .mainMagnitude (trend ,
354
+ self .k ,
355
+ self .n ,
356
+ self .freq ,
357
+ self .hfrac ,
358
+ self .lam ,
359
+ mapped_indices_cl , y_cl )
363
360
else :
364
- breaks , means = self .futobj .main (trend ,
365
- self .k ,
366
- self .n ,
367
- self .freq ,
368
- self .hfrac ,
369
- self .lam ,
370
- mapped_indices_cl , y_cl )
361
+ Ns , breaks , means = self .futobj .main (trend ,
362
+ self .k ,
363
+ self .n ,
364
+ self .freq ,
365
+ self .hfrac ,
366
+ self .lam ,
367
+ mapped_indices_cl , y_cl )
371
368
372
369
end = time .time ()
373
370
@@ -382,6 +379,7 @@ def _fit_single_kernel(self, y_cl, mapped_indices_cl):
382
379
results ['y_pred' ] = y_pred
383
380
results ['breaks' ] = breaks
384
381
results ['means' ] = means
382
+ results ['valids' ] = Ns
385
383
386
384
if self .find_magnitudes or self .detailed_results :
387
385
results ['magnitudes' ] = magnitudes
@@ -399,6 +397,7 @@ def _fit_single_postprocessing(self, results, oshape):
399
397
400
398
results ['breaks' ] = results ['breaks' ].get ().reshape (oshape [1 :])
401
399
results ['means' ] = results ['means' ].get ().reshape (oshape [1 :])
400
+ results ['valids' ] = results ['valids' ].get ().T .reshape (oshape [1 :])
402
401
403
402
if self .find_magnitudes or self .detailed_results :
404
403
results ['magnitudes' ] = results ['magnitudes' ].get ().reshape (oshape [1 :])
@@ -431,14 +430,18 @@ def __append_results(self, res, results):
431
430
else :
432
431
results ['means' ] = res ['means' ]
433
432
434
- if self .find_magnitudes or self .detailed :
433
+ if 'valids' in results .keys ():
434
+ results ['valids' ] = numpy .concatenate ([results ['valids' ], res ['valids' ]], axis = 0 )
435
+ else :
436
+ results ['valids' ] = res ['valids' ]
437
+
438
+ if self .find_magnitudes or self .detailed_results :
435
439
if 'magnitudes' in results .keys ():
436
440
results ['magnitudes' ] = numpy .concatenate ([results ['magnitudes' ], res ['magnitudes' ]], axis = 0 )
437
441
else :
438
442
results ['magnitudes' ] = res ['magnitudes' ]
439
443
440
444
if self .detailed_results :
441
-
442
445
if not 'bounds' in results .keys ():
443
446
results ['bounds' ] = res ['bounds' ]
444
447
0 commit comments