forked from chenzomi12/AISystem
-
Notifications
You must be signed in to change notification settings - Fork 0
/
05.srt
1540 lines (1155 loc) · 24.4 KB
/
05.srt
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
1
00:00:00,066 --> 00:00:03,833
字幕生成:qiaokai 字幕校对:mkwei
2
00:00:05,800 --> 00:00:09,566
大家好那个我是ZOMI
3
00:00:09,566 --> 00:00:10,133
那今天呢
4
00:00:10,133 --> 00:00:12,466
来到一个AI编译器系列之
5
00:00:12,466 --> 00:00:13,766
前端优化的
6
00:00:13,766 --> 00:00:14,733
布局转换
7
00:00:14,733 --> 00:00:15,866
这里面的布局转换呢
8
00:00:15,866 --> 00:00:17,566
主要是指数据布局
9
00:00:17,766 --> 00:00:19,399
那其实在上一个内容里面呢
10
00:00:19,400 --> 00:00:21,466
已经详细的去展开过了
11
00:00:21,466 --> 00:00:23,866
布局转换里面的前面的部分的内容
12
00:00:23,866 --> 00:00:26,766
第一个就是数据内存的排布
13
00:00:26,766 --> 00:00:27,466
数据呢
14
00:00:27,466 --> 00:00:29,999
在内存里面是怎么个排放的
15
00:00:30,266 --> 00:00:30,566
第二个呢
16
00:00:30,566 --> 00:00:33,999
讲了张量数据具体的排布方式
17
00:00:34,000 --> 00:00:36,266
第三个呢举了两个经典的例子
18
00:00:36,266 --> 00:00:38,666
NCHW和NHWC
19
00:00:38,733 --> 00:00:40,899
具体有什么区别
20
00:00:41,300 --> 00:00:43,300
接下来在这一节里面呢
21
00:00:43,300 --> 00:00:45,200
主要是讲下面这两个内容
22
00:00:45,200 --> 00:00:47,666
那第一个呢就是华为昇腾
23
00:00:47,666 --> 00:00:50,299
AI芯片的一个数据的排布方式
24
00:00:51,000 --> 00:00:53,000
这个内容我觉得是非常有意思的
25
00:00:53,000 --> 00:00:54,966
它不仅是代表华为昇腾
26
00:00:55,000 --> 00:00:56,966
也代表其他AI芯片厂商
27
00:00:56,966 --> 00:00:58,766
针对自己的芯片微架构呢
28
00:00:58,766 --> 00:01:00,266
提供特殊的数据存储和
29
00:01:00,266 --> 00:01:01,533
数据排布的方式
30
00:01:01,566 --> 00:01:02,466
那最后一个呢
31
00:01:02,466 --> 00:01:04,566
就是真正的回到今天的话题
32
00:01:04,566 --> 00:01:06,099
了解完基础知识之后呢
33
00:01:06,100 --> 00:01:07,100
来了解
34
00:01:07,266 --> 00:01:09,966
AI编译器对于数据布局
35
00:01:09,966 --> 00:01:11,799
转换优化的一个pass
36
00:01:11,800 --> 00:01:13,066
具体是怎么实现的
37
00:01:14,900 --> 00:01:17,333
接下来去了解一下华为昇腾
38
00:01:17,333 --> 00:01:19,399
处理器的一个数据排布
39
00:01:20,100 --> 00:01:22,100
在华为昇腾AI处理器当中呢
40
00:01:22,100 --> 00:01:25,000
为了提高整体的一个通用矩阵乘法
41
00:01:25,000 --> 00:01:26,900
即GEMM的一个运算速率
42
00:01:27,100 --> 00:01:28,466
和访存的效率
43
00:01:28,500 --> 00:01:30,733
所以呢所有的张量呢
44
00:01:30,733 --> 00:01:34,199
一般来说都不会使用NCHW这种方式
45
00:01:34,200 --> 00:01:39,200
而是把C进行切分采用的NCHWC0的方式
46
00:01:39,200 --> 00:01:42,200
那有时候呢内部呢叫做5HD的
47
00:01:42,200 --> 00:01:43,100
数据的方式
48
00:01:43,500 --> 00:01:44,366
那我现在呢
49
00:01:44,366 --> 00:01:47,166
以一个三维的数据作为例子
50
00:01:47,166 --> 00:01:48,799
就是HWC
51
00:01:49,000 --> 00:01:52,000
那H呢就是feature map的一个长和宽
52
00:01:52,100 --> 00:01:54,300
C呢就是Channel的大小
53
00:01:54,300 --> 00:01:55,666
那这个是三维的
54
00:01:55,800 --> 00:01:57,966
然后呢会把NHWC
55
00:01:57,966 --> 00:01:58,566
N呢
56
00:01:58,566 --> 00:02:01,133
其实还有一维 batch size的那个维度
57
00:02:01,133 --> 00:02:03,333
N呢现在先把它抛到一边
58
00:02:03,333 --> 00:02:05,066
因为它基本上没有变化
59
00:02:05,766 --> 00:02:06,333
接着呢
60
00:02:06,333 --> 00:02:09,299
对HWC里面的C channel进行切分
61
00:02:09,300 --> 00:02:12,866
里面呢切分成为c个C0
62
00:02:13,266 --> 00:02:14,399
所以可以看到
63
00:02:14,500 --> 00:02:16,100
传统的C这个channel
64
00:02:16,100 --> 00:02:19,800
把它切成多个C0 C1呢就等于4了
65
00:02:19,800 --> 00:02:23,766
1234分别由四个颜色去代替
66
00:02:23,766 --> 00:02:24,699
而这里面呢
67
00:02:24,700 --> 00:02:28,200
最后可以看到HW呢是正常的
68
00:02:28,766 --> 00:02:30,566
channel数呢就变成C0
69
00:02:30,566 --> 00:02:32,133
而C1呢有四个
70
00:02:32,133 --> 00:02:34,799
这个就是华为昇腾处理器的5HD
71
00:02:34,800 --> 00:02:36,066
的数据存储格式
72
00:02:38,766 --> 00:02:41,599
哎ZOMI老师我有一个疑问嘿
73
00:02:41,600 --> 00:02:44,933
为什么要把c这个轴切出来
74
00:02:45,000 --> 00:02:47,766
切成两个C0和C1的两个轴呢
75
00:02:49,566 --> 00:02:51,266
其实C0这个轴块
76
00:02:51,266 --> 00:02:53,199
C0这个数字呢是跟
77
00:02:53,400 --> 00:02:55,733
昇腾里面的达芬奇的微架构是相关的
78
00:02:55,733 --> 00:02:57,299
等于AI core里面
79
00:02:57,300 --> 00:02:59,200
矩阵计算单元的大小
80
00:02:59,400 --> 00:03:03,000
那对于FP16类型呢这个C0呢就为16
81
00:03:03,000 --> 00:03:05,200
对于INT8这个类型呢为32
82
00:03:05,200 --> 00:03:06,933
刚好是对应四个字节
83
00:03:06,933 --> 00:03:09,133
FP16呢对应两个字节
84
00:03:09,400 --> 00:03:12,100
这部分的数据呢需要连续的存储的
85
00:03:12,100 --> 00:03:14,533
所以呢C1等于C除以C0
86
00:03:14,533 --> 00:03:17,333
如果结果不整除呢就要向上取整了
87
00:03:17,333 --> 00:03:20,066
保证所有的数据都能够对齐
88
00:03:20,066 --> 00:03:22,066
那至于数据为什么需要对齐
89
00:03:22,066 --> 00:03:22,666
这个概念呢
90
00:03:22,666 --> 00:03:24,366
在前一个内容里面
91
00:03:24,366 --> 00:03:26,533
其实已经跟大家汇报过了
92
00:03:28,166 --> 00:03:31,799
接下来呢看一下NHWC或者NCHW呢
93
00:03:31,900 --> 00:03:35,133
是怎么变成NC1HWC0的
94
00:03:35,266 --> 00:03:38,366
以NHWC作为一个例子
95
00:03:38,366 --> 00:03:40,699
其实啊不是说非常难
96
00:03:41,533 --> 00:03:43,566
在这里面呢会分为两步
97
00:03:43,566 --> 00:03:46,299
那第一步呢就是把NHWC的数据
98
00:03:46,300 --> 00:03:48,366
在C轴的维度进行分割
99
00:03:48,366 --> 00:03:51,733
变成一个C1份NHWC0
100
00:03:51,866 --> 00:03:55,199
接着呢会把C1份的NHWC0呢
101
00:03:55,200 --> 00:03:57,566
在内存里面连续的排列
102
00:03:58,133 --> 00:04:01,166
最后呢就变成了NC1HWC0
103
00:04:01,166 --> 00:04:03,699
那具体呢在PyTorch里面呢可能
104
00:04:03,800 --> 00:04:06,933
进行一个reshape成NHWC1C0
105
00:04:06,966 --> 00:04:10,066
然后transpose成03124
106
00:04:12,333 --> 00:04:13,666
接下来分享一个
107
00:04:13,666 --> 00:04:15,533
在达芬奇微架构里面一个
108
00:04:15,533 --> 00:04:17,199
比较有意思的一个点
109
00:04:17,333 --> 00:04:19,999
会额外提供两个数据的格式
110
00:04:20,000 --> 00:04:23,300
一个呢叫做FRACTAL Z
111
00:04:23,300 --> 00:04:25,366
一个呢叫做FRACTAL NZ
112
00:04:25,400 --> 00:04:28,266
那FRACTAL呢它是分形的意思
113
00:04:28,600 --> 00:04:31,500
因为达芬奇呢它是一个SIMD的架构
114
00:04:31,566 --> 00:04:33,366
cube核呢就是AI core
115
00:04:34,466 --> 00:04:38,799
输出的格式呢其实是NW1H1H0W0
116
00:04:38,866 --> 00:04:39,866
嗯比较复杂
117
00:04:39,866 --> 00:04:41,899
但是呢从下面这个图里面呢
118
00:04:41,900 --> 00:04:43,166
简单的去理解一下
119
00:04:43,366 --> 00:04:44,733
假设呢现在一次过呢
120
00:04:44,733 --> 00:04:46,399
除以一行的数据
121
00:04:46,400 --> 00:04:47,100
那这里面呢
122
00:04:47,100 --> 00:04:49,533
我每一次丢进去AI core里面呢
123
00:04:49,533 --> 00:04:51,566
我就会直接去把这里面的
124
00:04:51,600 --> 00:04:53,700
一个小窗口的数据处理完
125
00:04:53,700 --> 00:04:55,466
那处理这个小窗口的数据呢
126
00:04:55,700 --> 00:04:57,533
有点类似于进行卷积计算的时候呢
127
00:04:57,533 --> 00:04:59,899
就把一个小窗口的数据算完
128
00:04:59,933 --> 00:05:01,466
让有非常多的cube核
129
00:05:01,466 --> 00:05:03,099
所以可以同时去
130
00:05:03,100 --> 00:05:05,166
计算非常多的这种小窗口
131
00:05:05,166 --> 00:05:06,699
而这种小窗口的数据呢
132
00:05:06,700 --> 00:05:08,100
具体是怎么排布的呢
133
00:05:08,366 --> 00:05:10,333
这里面呢有好几种不同的方式
134
00:05:10,366 --> 00:05:12,366
一个呢就是小z大z
135
00:05:12,466 --> 00:05:14,933
那小z呢就像这种我先按行排布
136
00:05:14,933 --> 00:05:15,899
然后下一个
137
00:05:16,166 --> 00:05:17,266
在这个小窗口里面呢
138
00:05:17,266 --> 00:05:18,599
在按行进行取数据
139
00:05:18,600 --> 00:05:20,533
然后再按行进行取数据
140
00:05:20,566 --> 00:05:21,699
这种就是小z
141
00:05:21,766 --> 00:05:22,466
那大z呢
142
00:05:22,466 --> 00:05:24,599
就是在整个大的feature map里面呢
143
00:05:24,700 --> 00:05:26,133
不断的按行进行取
144
00:05:26,133 --> 00:05:27,799
然后不断的按行进行取
145
00:05:27,800 --> 00:05:29,766
那这种呢就是大z的意思
146
00:05:29,800 --> 00:05:32,866
那所谓的小n大Z呢就在块列呢
147
00:05:32,866 --> 00:05:34,599
按列的方式进行排序
148
00:05:34,600 --> 00:05:36,533
我先取完这一列再取第二列
149
00:05:36,533 --> 00:05:37,533
再取第三列
150
00:05:37,600 --> 00:05:40,000
那块之间呢按行的方式去处理
151
00:05:40,000 --> 00:05:41,766
就是小n大Z
152
00:05:42,066 --> 00:05:43,466
例如权重的数据呢
153
00:05:43,466 --> 00:05:45,266
会以这种方式进行存储
154
00:05:45,600 --> 00:05:47,600
最后一个呢就是小z大N
155
00:05:47,700 --> 00:05:50,133
块列呢跟第一个的内容是相同的
156
00:05:50,133 --> 00:05:51,766
块列按行进行排列
157
00:05:51,800 --> 00:05:54,400
但是块间呢是按列进行排列的
158
00:05:54,600 --> 00:05:55,866
例如卷积输出结果呢
159
00:05:55,866 --> 00:05:58,299
都会以小z大N的方式进行排列
160
00:05:58,333 --> 00:06:00,799
那这这个呢只是额外新增的知识
161
00:06:00,800 --> 00:06:02,500
至于为什么要这么排列
162
00:06:02,500 --> 00:06:04,200
为什么要用小z大Z
163
00:06:04,366 --> 00:06:05,933
来去存储feature map
164
00:06:06,066 --> 00:06:07,766
为什么要用小n大Z
165
00:06:07,866 --> 00:06:09,333
来去存储卷积呢
166
00:06:09,566 --> 00:06:10,899
这个在后面的
167
00:06:10,966 --> 00:06:13,666
AI芯片去介绍达芬奇架构的时候
168
00:06:13,666 --> 00:06:15,066
会给大家去展开
169
00:06:15,066 --> 00:06:17,566
只是在内存数据转换这个内容里面呢
170
00:06:17,566 --> 00:06:19,333
简单给大家演示
171
00:06:19,366 --> 00:06:21,166
不同的芯片厂商不同的硬件
172
00:06:21,166 --> 00:06:23,299
他会有自己的一个数据存储的格式
173
00:06:23,300 --> 00:06:25,000
而数据存储的格式呢
174
00:06:25,000 --> 00:06:26,766
是根据硬件的读取方式
175
00:06:26,766 --> 00:06:29,466
或者硬件的计算方式所决定的
176
00:06:30,666 --> 00:06:33,066
接下来来到了一个最重要内容
177
00:06:33,066 --> 00:06:35,666
就是编译布局转换的一个优化
178
00:06:35,666 --> 00:06:37,933
就是在真正的AI编译器里面
179
00:06:37,933 --> 00:06:41,133
是如何对数据进行转换优化的
180
00:06:41,300 --> 00:06:43,266
那其实呢现在还是这个内容
181
00:06:43,266 --> 00:06:44,966
只是呢现在真正的
182
00:06:45,000 --> 00:06:46,400
了解完基础知识之后呢
183
00:06:46,400 --> 00:06:48,300
深入到AI编译器里面
184
00:06:48,333 --> 00:06:50,666
具体怎么做转换
185
00:06:51,900 --> 00:06:52,666
来看看
186
00:06:52,666 --> 00:06:55,099
实际上在AI编译器系里面的layout transformation
187
00:06:55,100 --> 00:06:56,166
的目的就是希望
188
00:06:56,166 --> 00:06:57,966
将内部的数据的布局
189
00:06:57,966 --> 00:06:59,133
转换成为后端
190
00:06:59,133 --> 00:07:00,266
就是硬件
191
00:07:00,333 --> 00:07:01,999
很友好的方式
192
00:07:02,133 --> 00:07:03,133
所以刚才说了
193
00:07:03,133 --> 00:07:04,499
数据怎么排布
194
00:07:04,500 --> 00:07:06,500
是根据硬件的执行方式
195
00:07:06,500 --> 00:07:07,600
相关联的
196
00:07:07,600 --> 00:07:08,933
不是说我随便排都行
197
00:07:08,933 --> 00:07:10,133
在CPU里面
198
00:07:10,133 --> 00:07:12,333
在GPU里面的排布方式是不一样的
199
00:07:12,500 --> 00:07:13,466
包括在昇腾
200
00:07:13,466 --> 00:07:14,933
处理器里面的排布方式
201
00:07:14,933 --> 00:07:15,866
也是不同的
202
00:07:15,866 --> 00:07:17,533
那最重要的方式呢
203
00:07:17,533 --> 00:07:19,133
就是找到在计算图当中
204
00:07:19,166 --> 00:07:22,366
存储这个张量最佳的数据布局
205
00:07:22,566 --> 00:07:23,966
大家注意一个概念呢
206
00:07:23,966 --> 00:07:26,699
这里面呢是谈的计算图哦
207
00:07:26,800 --> 00:07:28,000
所以会在图层IR
208
00:07:28,000 --> 00:07:29,400
里面去实现这个pass
209
00:07:29,400 --> 00:07:30,800
或者实现这个转换
210
00:07:30,800 --> 00:07:33,200
然后呢将数据布局呢转换成为
211
00:07:33,200 --> 00:07:35,800
具体的节点插到图中呢
212
00:07:35,900 --> 00:07:37,666
那值得注意的方式就是
213
00:07:37,666 --> 00:07:38,699
数据布局呢
214
00:07:38,700 --> 00:07:41,800
是最终对性能有非常大的影响
215
00:07:41,900 --> 00:07:45,000
而且转换的操作也有非常大的开销
216
00:07:45,000 --> 00:07:47,366
每一次数据的转换就涉及到IO
217
00:07:47,366 --> 00:07:48,766
涉及到访存
218
00:07:49,866 --> 00:07:50,899
回顾一些之前讲
219
00:07:50,900 --> 00:07:52,733
过的一些比较通用的概念
220
00:07:52,733 --> 00:07:55,399
那第一个呢就是NCHW这种格式呢
221
00:07:55,400 --> 00:07:58,166
在GPU上面是运行的比较快的
222
00:07:58,166 --> 00:07:59,266
所以GPU上面呢
223
00:07:59,266 --> 00:08:02,066
默认的去使用NCHW这种格式
224
00:08:02,333 --> 00:08:03,666
例如达芬奇架构呢
225
00:08:03,666 --> 00:08:06,499
就会提供一个CANN这个硬件的库呢
226
00:08:06,500 --> 00:08:09,700
芯片使能层呢去解决这些问题的
227
00:08:10,166 --> 00:08:13,099
还有第三点呢就是一些边缘的设备
228
00:08:13,100 --> 00:08:15,566
例如很简单的就是手机
229
00:08:15,566 --> 00:08:18,399
手机这块SOC呢里面有丰富的IP
230
00:08:18,533 --> 00:08:21,099
包括arm端侧的GPU还有ISP
231
00:08:21,100 --> 00:08:24,400
还有DPU等不同的这一些计算单元
232
00:08:24,400 --> 00:08:25,966
那不同的计算单元之间呢
233
00:08:25,966 --> 00:08:28,333
可能会有不同的数据排布
234
00:08:28,400 --> 00:08:30,000
所以呢针对边缘设备
235
00:08:30,000 --> 00:08:32,133
可能就会有异构的计算单元
236
00:08:32,133 --> 00:08:32,766
这个时候呢
237
00:08:32,766 --> 00:08:36,299
数据的转换呢就显得非常的重要了
238
00:08:36,300 --> 00:08:37,533
AI编译器呢
239
00:08:37,533 --> 00:08:38,999
就是希望能够提供一种
240
00:08:39,266 --> 00:08:42,366
跨硬件的一个数据排布转换的方式
241
00:08:42,366 --> 00:08:44,533
方便对接到不同的后端
242
00:08:45,000 --> 00:08:47,000
所以这个故事呢就告诉
243
00:08:47,200 --> 00:08:47,966
在写AI
244
00:08:47,966 --> 00:08:49,866
算法或者实现AI算法的时候呢
245
00:08:49,866 --> 00:08:52,299
其实AI框架或者AI编译器啊
246
00:08:52,300 --> 00:08:55,100
帮做了很多感知不到的工作
247
00:08:55,100 --> 00:08:57,733
不要以为AI框架只是一个简单的库
248
00:08:57,733 --> 00:08:59,666
直接调用算子就完了
249
00:08:59,700 --> 00:09:01,733
AI框架其实里面的
250
00:09:01,733 --> 00:09:03,566
技术含量还是非常高的