-
Notifications
You must be signed in to change notification settings - Fork 15
/
talshf.F90
1974 lines (1926 loc) · 105 KB
/
talshf.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
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
!ExaTensor::TAL-SH: Device-unified user-level API:
!REVISION: 2020/10/02
!Copyright (C) 2014-2022 Dmitry I. Lyakh (Liakh)
!Copyright (C) 2014-2022 Oak Ridge National Laboratory (UT-Battelle)
!LICENSE: BSD 3-Clause
!-------------------------------------------------------------------
module talsh
use tensor_algebra_cpu_phi !device-specific tensor algebra API + basic
implicit none
private
!EXTERNAL PUBLIC:
public tensor_shape_t !CP-TAL tensor shape (Fortran)
public tensor_block_t !CP-TAL tensor block (Fortran)
public talsh_tens_signature_t !TAL-SH tensor signature
public talsh_tens_shape_t !TAL-SH tensor shape
public talsh_tens_data_t !TAL-SH tensor data descriptor
public MAX_SHAPE_STR_LEN !max length of a shape-defining string
public MAX_TENSOR_RANK !max tensor rank
public CPTAL_MAX_THREADS !max expected number of CPU OpenMP threads in CP-TAL
public mem_allocate !universal memory allocator
public mem_free !universal memory deallocator
public tensor_shape_rank !
public get_contr_pattern_dig !
public get_contr_pattern_sym !
public contr_pattern_rnd !
public prof_push,prof_pop !profiling
!PARAMETERS:
!Generic:
integer(INTD), private:: CONS_OUT=6 !default output device for this module
integer(INTD), private:: DEBUG=0 !debugging mode for this module
logical, private:: VERBOSE=.TRUE. !verbosity for errors
!Errors (keep consistent with "talsh.h"):
integer(C_INT), parameter, public:: TALSH_SUCCESS=0 !success
integer(C_INT), parameter, public:: TALSH_FAILURE=-666 !generic failure
integer(C_INT), parameter, public:: TALSH_NOT_AVAILABLE=-888 !information or feature not avaiable (in principle)
integer(C_INT), parameter, public:: TALSH_NOT_IMPLEMENTED=-999 !feature not implemented yet
integer(C_INT), parameter, public:: TALSH_NOT_INITIALIZED=1000000 !TALSH library has not been initialized yet
integer(C_INT), parameter, public:: TALSH_ALREADY_INITIALIZED=1000001 !TALSH library has already been initialized
integer(C_INT), parameter, public:: TALSH_INVALID_ARGS=1000002 !invalid arguments passed to a procedure
integer(C_INT), parameter, public:: TALSH_INTEGER_OVERFLOW=1000003 !integer overflow occurred
integer(C_INT), parameter, public:: TALSH_OBJECT_NOT_EMPTY=1000004 !object is not empty while expected so
integer(C_INT), parameter, public:: TALSH_OBJECT_IS_EMPTY=1000005 !object is empty while not expected so
integer(C_INT), parameter, public:: TALSH_IN_PROGRESS=1000006 !TAL-SH operation is still in progress (not finished)
integer(C_INT), parameter, public:: TALSH_NOT_ALLOWED=1000007 !request is not allowed by TAL-SH
integer(C_INT), parameter, public:: TALSH_LIMIT_EXCEEDED=1000008 !internal limit exceeded
integer(C_INT), parameter, public:: TALSH_NOT_FOUND=1000009 !requested object not found
!TAL-SH task status:
integer(C_INT), parameter, public:: TALSH_TASK_ERROR=1999999
integer(C_INT), parameter, public:: TALSH_TASK_EMPTY=2000000
integer(C_INT), parameter, public:: TALSH_TASK_SCHEDULED=2000001
integer(C_INT), parameter, public:: TALSH_TASK_STARTED=2000002
integer(C_INT), parameter, public:: TALSH_TASK_INPUT_READY=2000003
integer(C_INT), parameter, public:: TALSH_TASK_OUTPUT_READY=2000004
integer(C_INT), parameter, public:: TALSH_TASK_COMPLETED=2000005
!Host argument buffer:
integer(C_INT), private:: ALLOCATE_VIA_HAB=0 !if negative, regular Host memory will be used for tensors instead of HAB
integer(C_SIZE_T), parameter, private:: HAB_SIZE_DEFAULT=16777216 !default size of the Host argument buffer in bytes (none)
!Execution device:
integer(C_INT), private:: EXECUTION_DEVICE_KIND=DEV_DEFAULT !if set, the specified device kind will be used for tensor operation execution by default
integer(C_INT), private:: EXECUTION_DEVICE_ID=DEV_DEFAULT !if set, the specified device id within its kind will be used for tensor operation execution by default
!CP-TAL:
integer(C_INT), parameter, private:: CPTAL_MAX_TMP_FTENS=192 !max number of simultaneously existing temporary Fortran tensors for CP-TAL
!DERIVED TYPES:
!TAL-SH tensor block:
type, public, bind(C):: talsh_tens_t
type(C_PTR):: shape_p=C_NULL_PTR !shape of the tensor block
type(C_PTR):: dev_rsc=C_NULL_PTR !list of device resources occupied by the tensor block body on each device
type(C_PTR):: data_kind=C_NULL_PTR !list of data kinds for each device location occupied by the tensor body {R4,R8,C4,C8}
type(C_PTR):: avail=C_NULL_PTR !list of the data availability flags for each device location occupied by the tensor body
integer(C_INT):: dev_rsc_len=0 !capacity of .dev_rsc[], .data_kind[], .avail[]
integer(C_INT):: ndev=0 !number of devices the tensor block body resides on: ndev <= dev_rsc_len
end type talsh_tens_t
!Tensor operation argument (auxiliary type):
type, bind(C):: talshTensArg_t
type(C_PTR):: tens_p !pointer to a tensor block
integer(C_INT):: source_image !specific body image of that tensor block participating in the operation
end type talshTensArg_t
!TAL-SH task handle:
type, public, bind(C):: talsh_task_t
type(C_PTR):: task_p=C_NULL_PTR !pointer to the corresponding device-specific task object
integer(C_INT):: task_error=-1 !-1:undefined(task in progress or empty); 0:successfully completed; >0: error code
integer(C_INT):: dev_kind=DEV_NULL !device kind (DEV_NULL: uninitialized)
integer(C_INT):: data_kind=NO_TYPE !data kind {R4,R8,C4,C8}, NO_TYPE: uninitialized
integer(C_INT):: coherence=-1 !coherence control (-1:undefined)
integer(C_INT):: num_args=0 !number of tensor arguments participating in the tensor operation
type(talshTensArg_t):: tens_args(MAX_TENSOR_OPERANDS) !tensor arguments
real(C_DOUBLE):: data_vol=0d0 !total data volume (information)
real(C_DOUBLE):: flops=0d0 !number of floating point operations (information)
real(C_DOUBLE):: exec_time=0d0 !execution time in seconds (information)
end type talsh_task_t
!GLOBALS:
!Temporary Fortran tensors for CP-TAL:
integer(INTD), private:: ftens_len=0
type(tensor_block_t), target, private:: ftensor(1:CPTAL_MAX_TMP_FTENS)
!INTERFACES FOR EXTERNAL C/C++ FUNCTIONS:
interface
!TAL-SH helper functions:
!Check the validity of a data kind and get its size in bytes:
integer(C_INT) function talsh_valid_data_kind(datk,datk_size) bind(c,name='talshValidDataKind')
import
implicit none
integer(C_INT), intent(in), value:: datk
integer(C_INT), intent(out):: datk_size
end function talsh_valid_data_kind
!TAL-SH control C/C++ API:
!Initialize TAL-SH:
integer(C_INT) function talshInit(host_buf_size,host_arg_max,ngpus,gpu_list,nmics,mic_list,namds,amd_list)&
&bind(c,name='talshInit')
import
implicit none
integer(C_SIZE_T), intent(inout):: host_buf_size
integer(C_INT), intent(out):: host_arg_max
integer(C_INT), value, intent(in):: ngpus
integer(C_INT), intent(in):: gpu_list(*)
integer(C_INT), value, intent(in):: nmics
integer(C_INT), intent(in):: mic_list(*)
integer(C_INT), value, intent(in):: namds
integer(C_INT), intent(in):: amd_list(*)
end function talshInit
!Shutdown TAL-SH:
integer(C_INT) function talshShutdown() bind(c,name='talshShutdown')
import
implicit none
end function talshShutdown
!Get on-node device count for a specific device kind:
integer(C_INT) function talsh_device_count(dev_kind,dev_count) bind(c,name='talshDeviceCount')
import
implicit none
integer(C_INT), intent(in), value:: dev_kind
integer(C_INT), intent(out):: dev_count
end function talsh_device_count
!Get the flat device Id:
integer(C_INT) function talshFlatDevId(dev_kind,dev_num) bind(c,name='talshFlatDevId')
import
implicit none
integer(C_INT), value, intent(in):: dev_kind
integer(C_INT), value, intent(in):: dev_num
end function talshFlatDevId
!Get the kind-specific device Id:
integer(C_INT) function talshKindDevId(dev_id,dev_kind) bind(c,name='talshKindDevId')
import
implicit none
integer(C_INT), value, intent(in):: dev_id
integer(C_INT), intent(out):: dev_kind
end function talshKindDevId
!Query the state of a device:
integer(C_INT) function talshDeviceState_(dev_num,dev_kind) bind(c,name='talshDeviceState_')
import
implicit none
integer(C_INT), value, intent(in):: dev_num
integer(C_INT), value, intent(in):: dev_kind
end function talshDeviceState_
!Find the least busy device:
integer(C_INT) function talshDeviceBusyLeast_(dev_kind) bind(c,name='talshDeviceBusyLeast_')
import
implicit none
integer(C_INT), value, intent(in):: dev_kind
end function talshDeviceBusyLeast_
!Query the device memory size in bytes:
integer(C_SIZE_T) function talshDeviceMemorySize_(dev_num,dev_kind) bind(c,name='talshDeviceMemorySize_')
import
implicit none
integer(C_INT), value, intent(in):: dev_num
integer(C_INT), value, intent(in):: dev_kind
end function talshDeviceMemorySize_
!Query the device argument buffer size in bytes:
integer(C_SIZE_T) function talshDeviceBufferSize_(dev_num,dev_kind) bind(c,name='talshDeviceBufferSize_')
import
implicit none
integer(C_INT), value, intent(in):: dev_num
integer(C_INT), value, intent(in):: dev_kind
end function talshDeviceBufferSize_
!Query the device max tensor size in bytes:
integer(C_SIZE_T) function talshDeviceTensorSize_(dev_num,dev_kind) bind(c,name='talshDeviceTensorSize_')
import
implicit none
integer(C_INT), value, intent(in):: dev_num
integer(C_INT), value, intent(in):: dev_kind
end function talshDeviceTensorSize_
!Query the amount of free memory in the argument buffer of a given device:
integer(C_SIZE_T) function talshDeviceBufferFreeSize_(dev_num,dev_kind) bind(c,name='talshDeviceBufferFreeSize_')
import
implicit none
integer(C_INT), value, intent(in):: dev_num
integer(C_INT), value, intent(in):: dev_kind
end function talshDeviceBufferFreeSize_
!Start memory manager log:
subroutine talsh_mem_manager_log_start() bind(c,name='talshMemManagerLogStart')
end subroutine talsh_mem_manager_log_start
!Finish memory manager log:
subroutine talsh_mem_manager_log_finish() bind(c,name='talshMemManagerLogFinish')
end subroutine talsh_mem_manager_log_finish
!Print run-time TAL-SH statistics for chosen devices:
integer(C_INT) function talshStats_(dev_id,dev_kind) bind(c,name='talshStats_')
import
implicit none
integer(C_INT), value, intent(in):: dev_id
integer(C_INT), value, intent(in):: dev_kind
end function talshStats_
!TAL-SH tensor block C/C++ API:
!Check whether a tensor block is empty (only be called on defined tensor blocks!):
integer(C_INT) function talshTensorIsEmpty(tens_block) bind(c,name='talshTensorIsEmpty')
import
implicit none
type(C_PTR), value, intent(in):: tens_block
end function talshTensorIsEmpty
!Construct a tensor block:
integer(C_INT) function talshTensorConstruct_(tens_block,data_kind,tens_rank,tens_dims,dev_id,&
ext_mem,in_hab,init_method,init_val_real,init_val_imag) bind(c,name='talshTensorConstruct_')
import
implicit none
type(talsh_tens_t):: tens_block
integer(C_INT), value, intent(in):: data_kind
integer(C_INT), value, intent(in):: tens_rank
integer(C_INT), intent(in):: tens_dims(*)
integer(C_INT), value, intent(in):: dev_id
type(C_PTR), value:: ext_mem
integer(C_INT), value, intent(in):: in_hab
type(C_FUNPTR), value, intent(in):: init_method
real(C_DOUBLE), value, intent(in):: init_val_real
real(C_DOUBLE), value, intent(in):: init_val_imag
end function talshTensorConstruct_
!Destruct a tensor block:
integer(C_INT) function talshTensorDestruct(tens_block) bind(c,name='talshTensorDestruct')
import
implicit none
type(talsh_tens_t):: tens_block
end function talshTensorDestruct
!Get the rank of the tensor block:
integer(C_INT) function talshTensorRank(tens_block) bind(c,name='talshTensorRank')
import
implicit none
type(talsh_tens_t), intent(in):: tens_block
end function talshTensorRank
!Get the volume of the tensor block:
integer(C_SIZE_T) function talshTensorVolume(tens_block) bind(c,name='talshTensorVolume')
import
implicit none
type(talsh_tens_t), intent(in):: tens_block
end function talshTensorVolume
!Get the shape of the tensor block:
integer(C_INT) function talshTensorShape(tens_block,tens_shape) bind(c,name='talshTensorShape')
import
implicit none
type(talsh_tens_t), intent(in):: tens_block
type(talsh_tens_shape_t), intent(inout):: tens_shape
end function talshTensorShape
!Get the data kind of each tensor image:
integer(C_INT) function talshTensorDataKind(tens_block,num_images,data_kinds) bind(c,name='talshTensorDataKind')
import
implicit none
type(talsh_tens_t), intent(in):: tens_block
integer(C_INT), intent(out):: num_images
integer(C_INT), intent(inout):: data_kinds(*)
end function talshTensorDataKind
!Reshape the tensor to a compatible shape (same volume):
integer(C_INT) function talshTensorReshape(tens_block,tens_rank,tens_dims) bind(c,name='talshTensorReshape')
import
implicit none
type(talsh_tens_t), intent(inout):: tens_block
integer(C_INT), intent(in), value:: tens_rank
integer(C_INT), intent(in):: tens_dims(*)
end function talshTensorReshape
!Query the presence of the tensor block on device(s):
integer(C_INT) function talshTensorPresence_(tens_block,ncopies,copies,data_kinds,dev_kind,dev_id)&
&bind(c,name='talshTensorPresence_')
import
implicit none
type(talsh_tens_t), intent(in):: tens_block
integer(C_INT), intent(out):: ncopies
integer(C_INT), intent(inout):: copies(*)
integer(C_INT), intent(inout):: data_kinds(*)
integer(C_INT), value, intent(in):: dev_kind
integer(C_INT), value, intent(in):: dev_id
end function talshTensorPresence_
!Get access to the tensor body image for a subsequent initialization:
integer(C_INT) function talshTensorGetBodyAccess_(tens_block,body_p,data_kind,dev_id,dev_kind)&
&bind(c,name='talshTensorGetBodyAccess_')
import
implicit none
type(talsh_tens_t), intent(inout):: tens_block
type(C_PTR), intent(inout):: body_p
integer(C_INT), intent(in), value:: data_kind
integer(C_INT), intent(in), value:: dev_id
integer(C_INT), intent(in), value:: dev_kind
end function talshTensorGetBodyAccess_
!Get the scalar value of the rank-0 tensor:
integer(C_INT) function talshTensorGetScalar(tens_block,scalar_real,scalar_imag)&
&bind(c,name='talshTensorGetScalar')
import
implicit none
type(talsh_tens_t), intent(inout):: tens_block
real(C_DOUBLE), intent(out):: scalar_real
real(C_DOUBLE), intent(out):: scalar_imag
end function talshTensorGetScalar
!Print information about a TAL-SH tensor:
subroutine talsh_tensor_print_info(tens_block) bind(c,name='talshTensorPrintInfo')
import
implicit none
type(talsh_tens_t), intent(in):: tens_block
end subroutine talsh_tensor_print_info
!Print tensor elements larger by absolute value than some threshold:
subroutine talsh_tensor_print_body(tens_block,thresh) bind(c,name='talshTensorPrintBody')
import
implicit none
type(talsh_tens_t), intent(in):: tens_block
real(C_DOUBLE), intent(in), value:: thresh
end subroutine talsh_tensor_print_body
![DEBUG]: Compute the 1-norm of a tensor on Host CPU:
real(C_DOUBLE) function talshTensorImageNorm1_cpu(talsh_tens) bind(c,name='talshTensorImageNorm1_cpu')
import
implicit none
type(talsh_tens_t), intent(in):: talsh_tens
end function talshTensorImageNorm1_cpu
!TAL-SH task C/C++ API:
!Clean an uninitialized TAL-SH task before the use:
integer(C_INT) function talsh_task_clean(talsh_task) bind(c,name='talshTaskClean')
import
implicit none
type(talsh_task_t), intent(inout):: talsh_task
end function talsh_task_clean
!Destruct a TAL-SH task:
integer(C_INT) function talshTaskDestruct(talsh_task) bind(c,name='talshTaskDestruct')
import
implicit none
type(talsh_task_t), intent(inout):: talsh_task
end function talshTaskDestruct
!Get the device id the TAL-SH task is scheduled on:
integer(C_INT) function talshTaskDevId_(talsh_task,dev_kind) bind(c,name='talshTaskDevId_')
import
implicit none
type(talsh_task_t), intent(inout):: talsh_task
type(C_PTR), value:: dev_kind
end function talshTaskDevId_
!Get the TAL-SH task status:
integer(C_INT) function talshTaskStatus(talsh_task) bind(c,name='talshTaskStatus')
import
implicit none
type(talsh_task_t), intent(inout):: talsh_task
end function talshTaskStatus
!Check whether a TAL-SH task has completed:
integer(C_INT) function talshTaskComplete(talsh_task,stats,ierr) bind(c,name='talshTaskComplete')
import
implicit none
type(talsh_task_t), intent(inout):: talsh_task
integer(C_INT), intent(out):: stats
integer(C_INT), intent(out):: ierr
end function talshTaskComplete
!Wait upon completion of a TAL-SH task:
integer(C_INT) function talshTaskWait(talsh_task,stats) bind(c,name='talshTaskWait')
import
implicit none
type(talsh_task_t), intent(inout):: talsh_task
integer(C_INT), intent(out):: stats
end function talshTaskWait
!Wait upon completion of multiple TAL-SH tasks:
integer(C_INT) function talshTasksWait(ntasks,talsh_tasks,stats) bind(c,name='talshTasksWait')
import
implicit none
integer(C_INT), value, intent(in):: ntasks
type(talsh_task_t), intent(inout):: talsh_tasks(*)
integer(C_INT), intent(out):: stats(*)
end function talshTasksWait
!Get the TAL-SH task timings:
integer(C_INT) function talshTaskTime_(talsh_task,total,comput,input,output,mmul) bind(c,name='talshTaskTime_')
import
implicit none
type(talsh_task_t), intent(inout):: talsh_task
real(C_DOUBLE), intent(out):: total
real(C_DOUBLE), intent(out):: comput
real(C_DOUBLE), intent(out):: input
real(C_DOUBLE), intent(out):: output
real(C_DOUBLE), intent(out):: mmul
end function talshTaskTime_
!Print TAL-SH task info:
subroutine talsh_task_print_info(talsh_task) bind(c,name='talshTaskPrint')
import
implicit none
type(talsh_task_t), intent(in):: talsh_task
end subroutine talsh_task_print_info
!TAL-SH tensor operations C/C++ API:
!Place a tensor block on a specific device:
integer(C_INT) function talshTensorPlace_(tens,dev_id,dev_kind,dev_mem,copy_ctrl,talsh_task)&
&bind(c,name='talshTensorPlace_')
import
implicit none
type(talsh_tens_t), intent(inout):: tens
integer(C_INT), value, intent(in):: dev_id
integer(C_INT), value, intent(in):: dev_kind
type(C_PTR), value:: dev_mem
integer(C_INT), value, intent(in):: copy_ctrl
type(talsh_task_t), intent(inout):: talsh_task
end function talshTensorPlace_
!Discard a tensor block on a specific device:
integer(C_INT) function talshTensorDiscard_(tens,dev_id,dev_kind) bind(c,name='talshTensorDiscard_')
import
implicit none
type(talsh_tens_t), intent(inout):: tens
integer(C_INT), value, intent(in):: dev_id
integer(C_INT), value, intent(in):: dev_kind
end function talshTensorDiscard_
!Discard a tensor block on all devices except a specific device:
integer(C_INT) function talshTensorDiscardOther_(tens,dev_id,dev_kind) bind(c,name='talshTensorDiscardOther_')
import
implicit none
type(talsh_tens_t), intent(inout):: tens
integer(C_INT), value, intent(in):: dev_id
integer(C_INT), value, intent(in):: dev_kind
end function talshTensorDiscardOther_
!Tensor initialization:
integer(C_INT) function talshTensorInit_(dtens,val_real,val_imag,dev_id,dev_kind,copy_ctrl,talsh_task)&
&bind(c,name='talshTensorInit_')
import
implicit none
type(talsh_tens_t), intent(inout):: dtens
real(C_DOUBLE), value, intent(in):: val_real
real(C_DOUBLE), value, intent(in):: val_imag
integer(C_INT), value, intent(in):: dev_id
integer(C_INT), value, intent(in):: dev_kind
integer(C_INT), value, intent(in):: copy_ctrl
type(talsh_task_t), intent(inout):: talsh_task
end function talshTensorInit_
!Tensor scaling:
integer(C_INT) function talshTensorScale_(dtens,val_real,val_imag,dev_id,dev_kind,copy_ctrl,talsh_task)&
&bind(c,name='talshTensorScale_')
import
implicit none
type(talsh_tens_t), intent(inout):: dtens
real(C_DOUBLE), value, intent(in):: val_real
real(C_DOUBLE), value, intent(in):: val_imag
integer(C_INT), value, intent(in):: dev_id
integer(C_INT), value, intent(in):: dev_kind
integer(C_INT), value, intent(in):: copy_ctrl
type(talsh_task_t), intent(inout):: talsh_task
end function talshTensorScale_
!Tensor slicing:
integer(C_INT) function talshTensorSlice_(dtens,ltens,offsets,dev_id,dev_kind,copy_ctrl,accumulative,talsh_task)&
&bind(c,name='talshTensorSlice_')
import
implicit none
type(talsh_tens_t), intent(inout):: dtens
type(talsh_tens_t), intent(inout):: ltens
integer(C_INT), intent(in):: offsets(*)
integer(C_INT), value, intent(in):: dev_id
integer(C_INT), value, intent(in):: dev_kind
integer(C_INT), value, intent(in):: copy_ctrl
integer(C_INT), value, intent(in):: accumulative
type(talsh_task_t), intent(inout):: talsh_task
end function talshTensorSlice_
!Tensor insertion:
integer(C_INT) function talshTensorInsert_(dtens,ltens,offsets,dev_id,dev_kind,copy_ctrl,accumulative,talsh_task)&
&bind(c,name='talshTensorInsert_')
import
implicit none
type(talsh_tens_t), intent(inout):: dtens
type(talsh_tens_t), intent(inout):: ltens
integer(C_INT), intent(in):: offsets(*)
integer(C_INT), value, intent(in):: dev_id
integer(C_INT), value, intent(in):: dev_kind
integer(C_INT), value, intent(in):: copy_ctrl
integer(C_INT), value, intent(in):: accumulative
type(talsh_task_t), intent(inout):: talsh_task
end function talshTensorInsert_
!Tensor copy:
integer(C_INT) function talshTensorCopy_(cptrn,dtens,ltens,dev_id,dev_kind,copy_ctrl,talsh_task)&
&bind(c,name='talshTensorCopy_')
import
implicit none
character(C_CHAR), intent(in):: cptrn(*)
type(talsh_tens_t), intent(inout):: dtens
type(talsh_tens_t), intent(inout):: ltens
integer(C_INT), value, intent(in):: dev_id
integer(C_INT), value, intent(in):: dev_kind
integer(C_INT), value, intent(in):: copy_ctrl
type(talsh_task_t), intent(inout):: talsh_task
end function talshTensorCopy_
!Tensor addition:
integer(C_INT) function talshTensorAdd_(cptrn,dtens,ltens,scale_real,scale_imag,dev_id,dev_kind,&
©_ctrl,talsh_task) bind(c,name='talshTensorAdd_')
import
implicit none
character(C_CHAR), intent(in):: cptrn(*)
type(talsh_tens_t), intent(inout):: dtens
type(talsh_tens_t), intent(inout):: ltens
real(C_DOUBLE), value, intent(in):: scale_real
real(C_DOUBLE), value, intent(in):: scale_imag
integer(C_INT), value, intent(in):: dev_id
integer(C_INT), value, intent(in):: dev_kind
integer(C_INT), value, intent(in):: copy_ctrl
type(talsh_task_t), intent(inout):: talsh_task
end function talshTensorAdd_
!Tensor contraction (regular):
integer(C_INT) function talshTensorContract_(cptrn,dtens,ltens,rtens,scale_real,scale_imag,dev_id,dev_kind,&
©_ctrl,accumulative,talsh_task) bind(c,name='talshTensorContract_')
import
implicit none
character(C_CHAR), intent(in):: cptrn(*)
type(talsh_tens_t), intent(inout):: dtens
type(talsh_tens_t), intent(inout):: ltens
type(talsh_tens_t), intent(inout):: rtens
real(C_DOUBLE), value, intent(in):: scale_real
real(C_DOUBLE), value, intent(in):: scale_imag
integer(C_INT), value, intent(in):: dev_id
integer(C_INT), value, intent(in):: dev_kind
integer(C_INT), value, intent(in):: copy_ctrl
integer(C_INT), value, intent(in):: accumulative
type(talsh_task_t), intent(inout):: talsh_task
end function talshTensorContract_
!Tensor contraction (extra large):
integer(C_INT) function talshTensorContractXL_(cptrn,dtens,ltens,rtens,scale_real,scale_imag,dev_id,dev_kind,&
&accumulative) bind(c,name='talshTensorContractXL_')
import
implicit none
character(C_CHAR), intent(in):: cptrn(*)
type(talsh_tens_t), intent(inout):: dtens
type(talsh_tens_t), intent(inout):: ltens
type(talsh_tens_t), intent(inout):: rtens
real(C_DOUBLE), value, intent(in):: scale_real
real(C_DOUBLE), value, intent(in):: scale_imag
integer(C_INT), value, intent(in):: dev_id
integer(C_INT), value, intent(in):: dev_kind
integer(C_INT), value, intent(in):: accumulative
end function talshTensorContractXL_
!Internal TAL-SH C/C++ API:
!Obtains the information on a specific tensor body image:
integer(C_INT) function talsh_tensor_image_info(talsh_tens,image_id,dev_id,data_kind,gmem_p,buf_entry)&
& bind(c,name='talsh_tensor_image_info')
import
implicit none
type(talsh_tens_t), intent(in):: talsh_tens
integer(C_INT), value, intent(in):: image_id
integer(C_INT), intent(out):: dev_id
integer(C_INT), intent(out):: data_kind
type(C_PTR), intent(out):: gmem_p
integer(C_INT), intent(out):: buf_entry
end function talsh_tensor_image_info
!CUDA runtime:
!Get on-node GPU device count:
integer(C_INT) function gpu_get_device_count(dev_count) bind(c,name='gpu_get_device_count')
import
implicit none
integer(C_INT), intent(out):: dev_count
end function gpu_get_device_count
end interface
!INTERFACES FOR OVERLOADED FOTRAN FUNCTIONS:
interface talsh_tensor_construct
module procedure talsh_tensor_construct_num
module procedure talsh_tensor_construct_sym
module procedure talsh_tensor_construct_shp
end interface talsh_tensor_construct
!VISIBILITY:
!TAL-SH helper API:
public talsh_valid_data_kind
!TAL-SH control API:
public talsh_init
public talsh_shutdown
public talsh_device_count
public talsh_flat_dev_id
public talsh_kind_dev_id
public talsh_device_state
public talsh_device_busy_least
public talsh_device_memory_size
public talsh_device_tensor_size
public talsh_device_buffer_free_size
public talsh_enforce_execution_device
public talsh_mem_manager_log_start
public talsh_mem_manager_log_finish
public talsh_stats
!TAL-SH tensor block API:
public talsh_tensor_is_empty
public talsh_tensor_construct
private talsh_tensor_construct_num
private talsh_tensor_construct_sym
private talsh_tensor_construct_shp
public talsh_tensor_destruct
public talsh_tensor_rank
public talsh_tensor_volume
public talsh_tensor_dimensions
public talsh_tensor_shape
public talsh_tensor_data_kind
public talsh_tensor_reshape
public talsh_tensor_presence
public talsh_tensor_get_body_access
public talsh_tensor_get_scalar
public talsh_tensor_print_info
public talsh_tensor_print_body
public talshTensorImageNorm1_cpu
!TAL-SH task API:
!private talsh_task_clean
public talsh_task_destruct
public talsh_task_dev_id
public talsh_task_status
public talsh_task_complete
public talsh_task_wait
public talsh_tasks_wait
public talsh_task_time
public talsh_task_print_info
!TAL-SH tensor operations API:
public talsh_tensor_place
public talsh_tensor_discard
public talsh_tensor_discard_other
public talsh_tensor_init
public talsh_tensor_scale
! public talsh_tensor_norm1
! public talsh_tensor_norm2
public talsh_tensor_slice
public talsh_tensor_insert
public talsh_tensor_copy
public talsh_tensor_add
public talsh_tensor_contract
public talsh_tensor_contract_xl
contains
!INTERNAL FUNCTIONS:
!--------------------------------------------------------------------------------------------------------
integer(C_INT) function talsh_get_contr_ptrn_str2dig(c_str,dig_ptrn,drank,lrank,rrank,conj_bits)&
&bind(c,name='talsh_get_contr_ptrn_str2dig')
implicit none
character(C_CHAR), intent(in):: c_str(1:*) !in: C-string (NULL terminated) containing the mnemonic contraction pattern
integer(C_INT), intent(out):: dig_ptrn(1:*) !out: digitial tensor contraction pattern
integer(C_INT), intent(out):: drank !out: destination tensor rank
integer(C_INT), intent(out):: lrank !out: left tensor rank
integer(C_INT), intent(out):: rrank !out: right tensor rank
integer(C_INT), intent(out):: conj_bits !out: argument complex conjugation flags (Bit 0 -> Destination, Bit 1 - > Left, Bit 2 -> Right)
integer, parameter:: MAX_CONTR_STR_LEN=1024 !max length of the tensor contraction string
integer:: dgp(MAX_TENSOR_RANK*2),dgl,csl,ierr
character(MAX_CONTR_STR_LEN):: contr_str
integer(INTD):: i,star_pos
talsh_get_contr_ptrn_str2dig=0
drank=-1; lrank=-1; rrank=-1; conj_bits=0
!Convert C-string to a Fortran string:
csl=1; star_pos=0
do while(iachar(c_str(csl)).ne.0)
if(csl.gt.MAX_CONTR_STR_LEN) then
talsh_get_contr_ptrn_str2dig=-1; return
endif
if(c_str(csl).eq.'*'.and.star_pos.eq.0) star_pos=csl
contr_str(csl:csl)=c_str(csl); csl=csl+1
enddo
csl=csl-1
!Add a fake third argument in case of addition:
if(star_pos.gt.0) then !check for possible scalar multiplication
i=index(contr_str(star_pos:csl),'(')+star_pos-1
if(i.lt.star_pos) then
csl=star_pos-1; star_pos=0 !remove scalar multiplication
if(csl.le.0) then; talsh_get_contr_ptrn_str2dig=-2; return; endif
if(contr_str(csl:csl).ne.')') then; talsh_get_contr_ptrn_str2dig=-3; return; endif
endif
endif
if(star_pos.eq.0) then !this is not a contraction (less than three arguments)
i=len('*R()'); contr_str(csl+1:csl+i)='*R()'; csl=csl+i !add a fake third argument (cast as a contraction)
endif
!Call converter from CP-TAL:
if(csl.gt.0) then
call get_contr_pattern_dig(contr_str(1:csl),drank,lrank,rrank,dgp,ierr,conj_bits)
if(ierr.eq.0) then
dgl=lrank+rrank; if(dgl.gt.0) dig_ptrn(1:dgl)=dgp(1:dgl)
else
talsh_get_contr_ptrn_str2dig=ierr; return
endif
endif
return
end function talsh_get_contr_ptrn_str2dig
!------------------------------------------
subroutine get_f_tensor(ftens,ierr)
implicit none
type(tensor_block_t), intent(out), pointer:: ftens
integer(INTD), intent(out):: ierr
ierr=0
!$OMP CRITICAL (CPTAL_TMP_FTENS)
if(ftens_len.lt.CPTAL_MAX_TMP_FTENS) then
ftens_len=ftens_len+1
ftens=>ftensor(ftens_len)
else
ftens=>NULL(); ierr=-1
endif
!$OMP END CRITICAL (CPTAL_TMP_FTENS)
return
end subroutine get_f_tensor
!---------------------------------------------
subroutine return_f_tensor(ftens,ierr)
implicit none
type(tensor_block_t), intent(in), pointer:: ftens
integer(INTD), intent(out):: ierr
type(tensor_block_t), pointer:: ft
integer(INTD):: i
ierr=0
!$OMP CRITICAL (CPTAL_TMP_FTENS)
if(associated(ftens)) then
do i=ftens_len,1,-1
ft=>ftensor(i)
if(associated(ft,ftens)) then; exit; else; ft=>NULL(); endif
enddo
if(associated(ft).and.(i.ge.1.and.i.le.ftens_len)) then
if(i.ne.ftens_len) ftensor(i)=ftensor(ftens_len) !move tensor_block_t (it has no allocatable components)
ftens_len=ftens_len-1
else
ierr=-2
endif
else
ierr=-1
endif
!$OMP END CRITICAL (CPTAL_TMP_FTENS)
return
end subroutine return_f_tensor
!------------------------------------------------------------------------------------------------------------------
integer(C_INT) function talsh_tensor_f_assoc(talsh_tens,image_id,tensF) bind(c,name='talsh_tensor_f_assoc')
!Returns a C pointer <tensF> to a <tensor_block_t> object instantiated with the tensor body image <image_id>.
!A return status TALSH_NOT_ALLOWED indicates that the requested tensor body image
!is no longer available (to be discarded by runtime).
implicit none
type(talsh_tens_t), intent(in):: talsh_tens !in: TAL-SH tensor
integer(C_INT), value, intent(in):: image_id !in: tensor body image id
type(C_PTR), intent(out):: tensF !out: C pointer to <tensor_block_t> associated with the TAL-SH tensor image
type(tensor_block_t), pointer:: ftens
type(talsh_tens_shape_t), pointer:: tens_shape
type(tensor_shape_t):: tshape
integer(C_INT), pointer, contiguous:: dims(:),divs(:),grps(:)
integer(C_INT):: devid,dtk,buf_entry,errc
type(C_PTR):: gmem_p
integer(INTD):: n,ierr
talsh_tensor_f_assoc=TALSH_SUCCESS
if(.not.talsh_tensor_is_empty(talsh_tens)) then
if(image_id.ge.0.and.image_id.lt.talsh_tens%ndev) then
if(c_associated(talsh_tens%dev_rsc).and.c_associated(talsh_tens%data_kind).and.c_associated(talsh_tens%avail).and.&
&talsh_tens%ndev.gt.0.and.talsh_tens%ndev.le.talsh_tens%dev_rsc_len) then
call c_f_pointer(talsh_tens%shape_p,tens_shape)
n=tens_shape%num_dim
if(n.ge.0) then
call get_f_tensor(ftens,ierr)
if(ierr.eq.0) then
if(n.gt.0) then
if(c_associated(tens_shape%dims)) then
call c_f_pointer(tens_shape%dims,dims,shape=(/n/))
else
dims=>NULL()
endif
if(c_associated(tens_shape%divs)) then
call c_f_pointer(tens_shape%divs,divs,shape=(/n/))
else
divs=>NULL()
endif
if(c_associated(tens_shape%grps)) then
call c_f_pointer(tens_shape%grps,grps,shape=(/n/))
else
grps=>NULL()
endif
else
dims=>NULL(); divs=>NULL(); grps=>NULL()
endif
call tensor_shape_assoc(tshape,ierr,dims,divs,grps)
if(ierr.eq.0) then
errc=talsh_tensor_image_info(talsh_tens,image_id,devid,dtk,gmem_p,buf_entry)
if(errc.eq.0) then
call tensor_block_assoc(ftens,tshape,dtk,gmem_p,errc)
if(errc.ne.0) talsh_tensor_f_assoc=TALSH_FAILURE
else
if(errc.eq.TALSH_NOT_ALLOWED) then
talsh_tensor_f_assoc=TALSH_NOT_ALLOWED !requested image is not available (to be discarded)
else
talsh_tensor_f_assoc=TALSH_FAILURE
endif
endif
else
talsh_tensor_f_assoc=TALSH_FAILURE
endif
if(talsh_tensor_f_assoc.eq.TALSH_SUCCESS) then
tensF=c_loc(ftens)
else
call tensor_block_destroy(ftens,ierr)
call return_f_tensor(ftens,ierr); if(ierr.ne.0) talsh_tensor_f_assoc=TALSH_FAILURE
tensF=C_NULL_PTR
endif
else
talsh_tensor_f_assoc=TRY_LATER
endif
else
talsh_tensor_f_assoc=TALSH_FAILURE
endif
else
talsh_tensor_f_assoc=TALSH_FAILURE
endif
else
talsh_tensor_f_assoc=TALSH_INVALID_ARGS
endif
else
talsh_tensor_f_assoc=TALSH_OBJECT_IS_EMPTY
endif
return
end function talsh_tensor_f_assoc
!------------------------------------------------------------------------------------------------
integer(C_INT) function talsh_tensor_f_dissoc(tensF) bind(c,name='talsh_tensor_f_dissoc')
!Destroys a temporary <tensor_block_t> object associated with a specific image of some TAL-SH tensor.
implicit none
type(C_PTR), value:: tensF !in: C pointer to a dynamically allocated <tensor_block_t> object by <talsh_tensor_f_assoc()>
type(tensor_block_t), pointer:: ftens
integer:: ierr
talsh_tensor_f_dissoc=TALSH_SUCCESS
if(c_associated(tensF)) then
call c_f_pointer(tensF,ftens)
if(.not.tensor_block_is_empty(ftens,ierr)) then
if(ierr.eq.0) then
call tensor_block_destroy(ftens,ierr)
if(ierr.ne.0) then
if(ierr.eq.NOT_CLEAN) then
talsh_tensor_f_dissoc=NOT_CLEAN
else
talsh_tensor_f_dissoc=TALSH_FAILURE
endif
endif
call return_f_tensor(ftens,ierr)
if(ierr.ne.0.and.talsh_tensor_f_dissoc.eq.TALSH_SUCCESS) talsh_tensor_f_dissoc=TALSH_FAILURE
else
talsh_tensor_f_dissoc=TALSH_FAILURE
endif
else
talsh_tensor_f_dissoc=TALSH_OBJECT_IS_EMPTY
endif
else
talsh_tensor_f_dissoc=TALSH_OBJECT_IS_EMPTY
endif
return
end function talsh_tensor_f_dissoc
!----------------------------------------------------------------------------
integer(C_INT) function talsh_update_f_scalar(tensF,data_kind,gmem_p) bind(c,name='talsh_update_f_scalar')
!Updates the given memory location <gmem_p> with the value of a scalar tensor.
!The memory location is the (single-element) body of a scalar tensor of type <talsh_tens_t>.
implicit none
type(C_PTR), value:: tensF !in: C pointer to <tensor_block_t>
integer(C_INT), intent(in), value:: data_kind !in: data kind
type(C_PTR), value:: gmem_p !in: C pointer to the single-element body of a <talsh_tens_t> image
type(tensor_block_t), pointer:: ftens
integer:: ierr
real(4), pointer:: r4p
real(8), pointer:: r8p
complex(4), pointer:: c4p
complex(8), pointer:: c8p
complex(8):: val
talsh_update_f_scalar=TALSH_SUCCESS
if(c_associated(tensF)) then
call c_f_pointer(tensF,ftens)
if(.not.tensor_block_is_empty(ftens,ierr)) then
if(ierr.eq.0) then
if(c_associated(gmem_p)) then
val=tensor_block_scalar_value(ftens)
select case(data_kind)
case(R4)
call c_f_pointer(gmem_p,r4p); r4p=real(val,4); r4p=>NULL()
case(R8)
call c_f_pointer(gmem_p,r8p); r8p=real(val,8); r8p=>NULL()
case(C4)
call c_f_pointer(gmem_p,c4p); c4p=cmplx(real(val),imag(val),4); c4p=>NULL()
case(C8)
call c_f_pointer(gmem_p,c8p); c8p=val; c8p=>NULL()
case default
talsh_update_f_scalar=TALSH_INVALID_ARGS
end select
else
talsh_update_f_scalar=TALSH_INVALID_ARGS
endif
else
talsh_update_f_scalar=TALSH_FAILURE
endif
else
talsh_update_f_scalar=TALSH_OBJECT_IS_EMPTY
endif
else
talsh_update_f_scalar=TALSH_OBJECT_IS_EMPTY
endif
return
end function talsh_update_f_scalar
!---------------------------------------------------------------------------------------------------------------------
subroutine talsh_set_mem_alloc_policy_host(mem_policy,fallback,ierr) bind(c,name='talshSetMemAllocPolicyHost')
!Wrapper for CP-TAL set_mem_alloc_policy() for C/C++.
implicit none
integer(C_INT), intent(in), value:: mem_policy !in: CPU memory allocation policy for CP-TAL
integer(C_INT), intent(in), value:: fallback !in: fallback to regular allocation
integer(C_INT), intent(out):: ierr !out: error code
integer:: mem_pol,errc
logical:: fb
mem_pol=mem_policy; fb=(fallback.ne.0)
call set_mem_alloc_policy(mem_pol,errc,fb); ierr=errc
return
end subroutine talsh_set_mem_alloc_policy_host
!-----------------------------------------------------
!FORTRAN TAL-SH API DEFINITIONS:
!TAL-SH control API:
!----------------------------------------------------------------------------------------------
function talsh_init(host_buf_size,host_arg_max,gpu_list,mic_list,amd_list) result(ierr)
implicit none
integer(C_INT):: ierr !out: error code (0:success)
integer(C_SIZE_T), intent(inout), optional:: host_buf_size !inout: desired size in bytes of the Host Argument Buffer (HAB).
! It will be replaced by the actual size.
integer(C_INT), intent(out), optional:: host_arg_max !out: max number of arguments the HAB can contain
integer(C_INT), intent(in), optional:: gpu_list(1:) !in: list of NVidia GPU's to use
integer(C_INT), intent(in), optional:: mic_list(1:) !in: list of Intel Xeon Phi's to use
integer(C_INT), intent(in), optional:: amd_list(1:) !in: list of AMD GPU's to use
integer(C_INT):: ngpus,gpus(MAX_GPUS_PER_NODE)
integer(C_INT):: nmics,mics(MAX_MICS_PER_NODE)
integer(C_INT):: namds,amds(MAX_AMDS_PER_NODE)
integer(C_SIZE_T):: hbuf_size
integer(C_INT):: harg_max
if(present(host_buf_size)) then
ALLOCATE_VIA_HAB=0
hbuf_size=host_buf_size
else
ALLOCATE_VIA_HAB=-1
hbuf_size=HAB_SIZE_DEFAULT
endif
if(present(gpu_list)) then; ngpus=size(gpu_list); gpus(1:ngpus)=gpu_list(1:ngpus); else; ngpus=0; endif
if(present(mic_list)) then; nmics=size(mic_list); mics(1:nmics)=mic_list(1:nmics); else; nmics=0; endif
if(present(amd_list)) then; namds=size(amd_list); amds(1:namds)=amd_list(1:namds); else; namds=0; endif
ierr=talshInit(hbuf_size,harg_max,ngpus,gpus,nmics,mics,namds,amds)
if(present(host_arg_max)) host_arg_max=harg_max
if(present(host_buf_size)) host_buf_size=hbuf_size
return
end function talsh_init
!---------------------------------------------
function talsh_shutdown() result(ierr)
implicit none
integer(C_INT):: ierr !out: error code (0:success)
ierr=talshShutdown()
return
end function talsh_shutdown
!----------------------------------------------------------------
function talsh_flat_dev_id(dev_kind,dev_num) result(res)
implicit none
integer(C_INT):: res !out: flat device Id [0..DEV_MAX-1]; Failure: DEV_MAX
integer(C_INT), intent(in):: dev_kind !in: device kind
integer(C_INT), intent(in):: dev_num !in: device Id within its kind (0..MAX)
res=talshFlatDevId(dev_kind,dev_num)
return
end function talsh_flat_dev_id
!--------------------------------------------------------------
function talsh_kind_dev_id(dev_id,dev_kind) result(res)
implicit none
integer(C_INT):: res !out: kind-specific device Id [0..MAX]; Failure: DEV_NULL (negative)
integer(C_INT), intent(in):: dev_id !in: flat device Id
integer(C_INT), intent(out):: dev_kind !out: device kind
res=talshKindDevId(dev_id,dev_kind)
return
end function talsh_kind_dev_id
!----------------------------------------------------------------------
function talsh_device_state(dev_num,dev_kind) result(dev_state)
implicit none
integer(C_INT):: dev_state !out: device state (Success:[DEV_OFF,DEV_ON,DEV_ON_BLAS])
integer(C_INT), intent(in):: dev_num !in: either a flat or kind specific (when <dev_kind> is present) device id
integer(C_INT), intent(in), optional:: dev_kind !in: device kind (note that it changes the meaning of the <dev_num> argument)
integer(C_INT):: devk
if(present(dev_kind)) then; devk=dev_kind; else; devk=DEV_NULL; endif
dev_state=talshDeviceState_(dev_num,devk)
return
end function talsh_device_state
!----------------------------------------------------------------
function talsh_device_busy_least(dev_kind) result(dev_id)
implicit none
integer(C_INT):: dev_id !out: either a flat or kind specific device id
integer(C_INT), intent(in), optional:: dev_kind !in: device kind (if absent, <dev_id> will return the flat device id)
integer(C_INT):: devk
if(present(dev_kind)) then; devk=dev_kind; else; devk=DEV_NULL; endif
dev_id=talshDeviceBusyLeast_(devk)
return
end function talsh_device_busy_least
!---------------------------------------------------------------------------
function talsh_device_memory_size(dev_num,dev_kind) result(mem_size)
implicit none
integer(C_SIZE_T):: mem_size !out: device memory size in bytes
integer(C_INT), intent(in):: dev_num !in: either a flat or kind specific (when <dev_kind> is present) device id
integer(C_INT), intent(in), optional:: dev_kind !in: device kind (note that it changes the meaning of the <dev_num> argument)
integer(C_INT):: devk
if(present(dev_kind)) then; devk=dev_kind; else; devk=DEV_NULL; endif
mem_size=talshDeviceMemorySize_(dev_num,devk)
return
end function talsh_device_memory_size
!----------------------------------------------------------------------------
function talsh_device_tensor_size(dev_num,dev_kind) result(tens_size)
implicit none
integer(C_SIZE_T):: tens_size !out: max tensor size in bytes on a given device
integer(C_INT), intent(in):: dev_num !in: either a flat or kind specific (when <dev_kind> is present) device id
integer(C_INT), intent(in), optional:: dev_kind !in: device kind (note that it changes the meaning of the <dev_num> argument)
integer(C_INT):: devk
if(present(dev_kind)) then; devk=dev_kind; else; devk=DEV_NULL; endif
tens_size=talshDeviceTensorSize_(dev_num,devk)
return
end function talsh_device_tensor_size