forked from chenzomi12/AISystem
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path01.srt
1552 lines (1165 loc) · 23.9 KB
/
01.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,117 --> 00:00:05,498
【字幕生成: 奔崩 字幕校对: 奔崩】
2
00:00:05,560 --> 00:00:06,440
哈喽大家好
3
00:00:06,440 --> 00:00:09,120
我是那个身体倍儿棒的ZOMI
4
00:00:09,400 --> 00:00:10,800
可能讲完这一话之后
5
00:00:10,920 --> 00:00:12,160
我已经病倒了
6
00:00:12,840 --> 00:00:14,800
今天来到一个新的内容
7
00:00:15,800 --> 00:00:17,120
这话招人打
8
00:00:17,880 --> 00:00:18,560
新的内容
9
00:00:18,560 --> 00:00:20,880
AI编译器的后端优化
10
00:00:21,080 --> 00:00:22,280
后端优化这个话题
11
00:00:22,280 --> 00:00:23,320
还是很有意思的
12
00:00:23,320 --> 00:00:24,960
今天要给大家汇报一下
13
00:00:24,960 --> 00:00:26,920
接下来要讲哪些内容
14
00:00:26,920 --> 00:00:29,160
首先今天的主要的内容
15
00:00:29,160 --> 00:00:31,200
就是去看看整个后端优化的
16
00:00:31,200 --> 00:00:32,120
整体的概念
17
00:00:32,120 --> 00:00:33,480
什么是后端优化
18
00:00:33,480 --> 00:00:35,880
后端优化会做些什么东西
19
00:00:35,880 --> 00:00:37,400
接着去看看
20
00:00:37,400 --> 00:00:39,280
算子的执行和调度
21
00:00:39,280 --> 00:00:42,720
其实后端优化主要的优化的内容
22
00:00:42,720 --> 00:00:44,320
就是算子的执行
23
00:00:44,320 --> 00:00:45,760
和它的调度方式
24
00:00:46,040 --> 00:00:46,880
执行和调度
25
00:00:47,080 --> 00:00:48,920
最重要的就是调度这一块
26
00:00:48,920 --> 00:00:50,600
怎么在不同的硬件上面调度
27
00:00:50,600 --> 00:00:52,200
于是就会去展开一个
28
00:00:52,200 --> 00:00:53,200
很重要的概念
29
00:00:53,720 --> 00:00:56,040
这是算子的循环优化
30
00:00:56,040 --> 00:00:57,720
在算子的循环优化
31
00:00:57,720 --> 00:00:59,000
具体的实现过程
32
00:00:59,240 --> 00:01:01,600
其实现在业界是有两条路径的
33
00:01:01,600 --> 00:01:03,600
一条是走Auto-tuning的路径
34
00:01:03,600 --> 00:01:05,748
一条是走Polyhedral
35
00:01:05,748 --> 00:01:06,840
多面体的技术
36
00:01:06,840 --> 00:01:08,520
将会分开两个点
37
00:01:08,520 --> 00:01:10,000
去给大家汇报的
38
00:01:11,400 --> 00:01:12,840
现在正式的进入
39
00:01:12,840 --> 00:01:14,160
这个内容里面
40
00:01:14,160 --> 00:01:15,240
首先看一下
41
00:01:15,240 --> 00:01:17,160
整个AI编译器的架构图
42
00:01:17,160 --> 00:01:18,240
从上往下
43
00:01:18,240 --> 00:01:20,480
首先用Python写了一些
44
00:01:21,080 --> 00:01:22,360
神经网络的代码
45
00:01:22,480 --> 00:01:23,960
这些代码是调用
46
00:01:23,960 --> 00:01:25,440
AI框架的API的
47
00:01:25,680 --> 00:01:27,160
AI框架就会帮
48
00:01:27,160 --> 00:01:28,560
把一些写的Python的代码
49
00:01:28,600 --> 00:01:29,880
转成Graph IR
50
00:01:29,880 --> 00:01:30,840
就是计算图
51
00:01:30,840 --> 00:01:32,800
接着会做一些图算的融合
52
00:01:32,800 --> 00:01:35,680
内存排布、内存优化等不同的优化的Path
53
00:01:35,840 --> 00:01:36,720
这些优化的Path
54
00:01:36,880 --> 00:01:39,280
都是基于计算图去实现的
55
00:01:39,280 --> 00:01:40,760
接着再往下
56
00:01:40,760 --> 00:01:43,640
就是需要把高层的IR Graph IR
57
00:01:43,640 --> 00:01:44,400
计算图IR
58
00:01:44,400 --> 00:01:46,120
转成底层IR
59
00:01:46,120 --> 00:01:47,040
Tensor的IR
60
00:01:47,040 --> 00:01:48,680
或者叫OPS IR
61
00:01:48,680 --> 00:01:52,320
针对算子 OPS 去进行一个优化
62
00:01:52,560 --> 00:01:53,600
这里面的优化方式
63
00:01:53,760 --> 00:01:55,080
有循环优化、张量融合
64
00:01:55,080 --> 00:01:56,880
还有存储Tiling、还有张量化
65
00:01:57,000 --> 00:01:58,720
将会在第三节内容里面
66
00:01:58,720 --> 00:01:59,960
详细的展开
67
00:02:01,080 --> 00:02:03,040
进入到OPS Optimizer
68
00:02:03,040 --> 00:02:04,560
这一个就是正式的
69
00:02:04,560 --> 00:02:06,800
进入到后端优化的过程当中
70
00:02:07,600 --> 00:02:09,000
后面的Backend后端
71
00:02:09,120 --> 00:02:11,360
更多的是跟Core Gemm相关
72
00:02:11,360 --> 00:02:12,240
这一块的内容
73
00:02:12,440 --> 00:02:14,360
跟传统的编译器更加贴近
74
00:02:14,480 --> 00:02:16,680
在这个时候 其实不会展开太多
75
00:02:17,040 --> 00:02:19,040
主要是围绕着红色的这一框
76
00:02:19,360 --> 00:02:21,080
中间的OPS Optimizer
77
00:02:21,080 --> 00:02:22,440
这一层去展开
78
00:02:24,520 --> 00:02:26,640
下面重点的去看看
79
00:02:26,640 --> 00:02:27,760
Graph Optimizer
80
00:02:27,760 --> 00:02:29,160
跟OPS Optimizer
81
00:02:29,160 --> 00:02:31,200
一个主要的区别
82
00:02:31,560 --> 00:02:32,600
前端的优化
83
00:02:32,760 --> 00:02:34,280
就是Graph Optimizer
84
00:02:34,280 --> 00:02:36,040
输入是一个计算图
85
00:02:36,040 --> 00:02:38,520
这个时候 更关注于整个计算图的
86
00:02:38,520 --> 00:02:39,560
拓扑的优化
87
00:02:39,560 --> 00:02:42,160
而不是关心某个具体算子的实现
88
00:02:42,160 --> 00:02:44,000
从下面这个图 也可以看到
89
00:02:44,120 --> 00:02:45,960
左边的 这个是计算图
90
00:02:45,960 --> 00:02:47,640
进行了一些优化
91
00:02:47,640 --> 00:02:49,520
不断的 很多的优化的Path
92
00:02:49,520 --> 00:02:50,880
最终把左边
93
00:02:51,200 --> 00:02:52,600
有6个算子的计算图
94
00:02:52,920 --> 00:02:55,800
变成只有3个算子的计算图
95
00:02:56,400 --> 00:02:57,560
这里面可以看出
96
00:02:57,840 --> 00:02:59,520
在AI编辑器的前端优化
97
00:02:59,840 --> 00:03:01,760
主要是对算子的节点
98
00:03:01,760 --> 00:03:03,880
进行一些消除、融合、化简
99
00:03:04,160 --> 00:03:06,560
使得计算图整个的计算
100
00:03:06,560 --> 00:03:08,920
还有存储的开销 做到最小
101
00:03:08,920 --> 00:03:10,640
这个就是前端优化的目的
102
00:03:11,120 --> 00:03:12,120
下面来看看
103
00:03:12,120 --> 00:03:14,120
后端优化做了哪些工作
104
00:03:14,400 --> 00:03:15,360
而后端优化
105
00:03:15,520 --> 00:03:17,000
主要是关注于具体
106
00:03:17,000 --> 00:03:18,200
某个算子的
107
00:03:18,480 --> 00:03:19,720
具体内部实现
108
00:03:20,000 --> 00:03:21,520
这里面看看这个图
109
00:03:21,800 --> 00:03:23,880
左边是一个简单的神级网络
110
00:03:24,000 --> 00:03:26,080
针对这里面一个卷积的算子
111
00:03:26,400 --> 00:03:28,320
卷积算子 CPU的实现
112
00:03:28,760 --> 00:03:30,080
代码就像右边
113
00:03:30,440 --> 00:03:31,400
演示的一个代码
114
00:03:31,720 --> 00:03:33,600
具体希望能够实现
115
00:03:33,880 --> 00:03:34,920
达到性能的最优
116
00:03:35,200 --> 00:03:36,120
但可以看到
117
00:03:36,120 --> 00:03:37,960
其实它的嵌套非常的深
118
00:03:38,320 --> 00:03:40,760
这种嵌套或者这种方式去实现
119
00:03:41,080 --> 00:03:42,720
它性能绝对不是最优的
120
00:03:43,040 --> 00:03:44,520
所以去实现的过程当中
121
00:03:44,800 --> 00:03:47,200
就有非常多的优化的方式
122
00:03:47,480 --> 00:03:48,880
可以对输入输出
123
00:03:49,120 --> 00:03:50,560
还有内部的循环的方式
124
00:03:50,840 --> 00:03:52,120
还有内存的访问
125
00:03:52,960 --> 00:03:54,840
进行各种各样的优化
126
00:03:55,240 --> 00:03:57,840
这两点就是后端优化和前端优化
127
00:03:58,200 --> 00:03:59,560
最大的区别
128
00:04:01,320 --> 00:04:04,160
现在回到AI编辑器的后端优化
129
00:04:04,160 --> 00:04:05,440
去看一下后端优化的
130
00:04:05,760 --> 00:04:06,920
主要有哪几个步骤
131
00:04:07,280 --> 00:04:09,560
首先我把这里面分为三层
132
00:04:09,880 --> 00:04:11,640
第一层会把计算图
133
00:04:11,640 --> 00:04:12,760
就是高级IR
134
00:04:13,080 --> 00:04:14,800
转换成为Tensor IR
135
00:04:15,120 --> 00:04:16,280
或者OPS IR
136
00:04:16,840 --> 00:04:19,240
把高级的IR变成一个低级的IR
137
00:04:19,240 --> 00:04:19,880
这是第一步
138
00:04:20,240 --> 00:04:21,640
第二步就是正式的
139
00:04:21,640 --> 00:04:24,320
来到后端的算子的优化
140
00:04:24,320 --> 00:04:26,280
或者直接叫后端优化就完了
141
00:04:26,720 --> 00:04:27,760
接着后端优化
142
00:04:27,760 --> 00:04:30,160
会把它变成一个更lower的IR
143
00:04:30,160 --> 00:04:31,200
就更低级的IR
144
00:04:31,480 --> 00:04:33,600
然后去做一些代码的生成
145
00:04:33,760 --> 00:04:35,400
这里面就叫Core Gemm
146
00:04:36,720 --> 00:04:38,080
生成完具体的代码
147
00:04:38,080 --> 00:04:40,400
就会在硬件上面去执行
148
00:04:41,440 --> 00:04:43,240
下面详细去看一看
149
00:04:44,760 --> 00:04:47,600
首先第一步就是生成低级的IR
150
00:04:47,960 --> 00:04:50,120
其实针对某一个特定的算子
151
00:04:50,120 --> 00:04:51,400
例如 加 这个算子
152
00:04:51,600 --> 00:04:53,000
它不同的编译器
153
00:04:53,320 --> 00:04:54,960
不同的定义是不同的
154
00:04:55,200 --> 00:04:56,600
但是对于ADD这个算子
155
00:04:57,040 --> 00:04:59,800
它的算法的原理其实都是相同的
156
00:05:00,080 --> 00:05:01,680
所以针对每一个具体的算子
157
00:05:01,840 --> 00:05:04,040
需要用AI编译器的底层的接口
158
00:05:04,320 --> 00:05:06,080
去来定义这个算法
159
00:05:06,360 --> 00:05:07,760
这里面relay.add
160
00:05:07,760 --> 00:05:09,760
就是TVM IR的一个定义
161
00:05:10,040 --> 00:05:11,680
最后再由TVM的编译器
162
00:05:11,680 --> 00:05:15,360
来生成底层内部的一些更加低级的IR
163
00:05:15,600 --> 00:05:17,000
接下来看看第二步
164
00:05:17,000 --> 00:05:18,480
就是后端的优化
165
00:05:18,680 --> 00:05:19,560
后端的优化
166
00:05:19,560 --> 00:05:20,532
更多的是针对
167
00:05:20,532 --> 00:05:22,800
一些硬件的微架构或者架构
168
00:05:23,040 --> 00:05:25,280
不同的算法的实现方式不同
169
00:05:25,560 --> 00:05:27,480
例如举一个简单的例子
170
00:05:27,720 --> 00:05:29,320
我对卷积这个算子
171
00:05:29,560 --> 00:05:31,160
在某个特定的硬件架构
172
00:05:31,160 --> 00:05:32,360
例如华为达芬奇
173
00:05:32,600 --> 00:05:34,640
找到一个最优的实现方式能不能呢
174
00:05:34,960 --> 00:05:35,280
可以
175
00:05:35,680 --> 00:05:37,320
但是值得注意的一点
176
00:05:37,320 --> 00:05:38,680
就是一个算子
177
00:05:38,680 --> 00:05:40,840
Conv1×1、Conv3×3
178
00:05:41,120 --> 00:05:43,040
Conv5×5包括Conv7×7
179
00:05:43,400 --> 00:05:45,720
它的性能都是不一样的
180
00:05:46,120 --> 00:05:48,160
它的实现方式也是不一样的
181
00:05:48,480 --> 00:05:51,000
所以都会有不同的循环的优化方法
182
00:05:51,440 --> 00:05:53,920
这里面的优化方法就非常讲究了
183
00:05:53,920 --> 00:05:56,200
有人工实现的、有人工加经验
184
00:05:56,200 --> 00:05:57,236
也有AutoTuning
185
00:05:57,236 --> 00:05:58,640
自动去实现的这种方式
186
00:05:58,920 --> 00:06:00,120
三种不同的路径
187
00:06:00,840 --> 00:06:03,360
最后看看代码生成
188
00:06:03,760 --> 00:06:06,440
代码生成 会把刚才讲到的
189
00:06:07,200 --> 00:06:08,720
OPS IR或者Tensor IR
190
00:06:09,160 --> 00:06:11,640
再转换成为一个更低级的IR
191
00:06:11,640 --> 00:06:13,640
然后通过代码生成
192
00:06:13,920 --> 00:06:16,560
转换成为机器能够执行的一些指令
193
00:06:17,000 --> 00:06:19,480
这个其实不是AI编译器的核心内容
194
00:06:19,800 --> 00:06:22,560
例如怎么把底层的IR转换成为LLVM
195
00:06:22,920 --> 00:06:25,280
或者NVCC英伟达推出的编译器
196
00:06:25,960 --> 00:06:26,880
AI火起来之后
197
00:06:27,000 --> 00:06:29,840
这些古老的技术也是随着火起来了
198
00:06:31,759 --> 00:06:34,040
(战术变声)
ZOMI老师 我有一个问题
199
00:06:34,520 --> 00:06:36,200
为什么AI的后端优化
200
00:06:36,200 --> 00:06:38,480
不直接用传统的通用的编译器
201
00:06:39,120 --> 00:06:40,600
就好像GCC LLVM
202
00:06:40,960 --> 00:06:43,320
去替换掉后端的优化可以吗
203
00:06:43,320 --> 00:06:46,440
这个问题问得非常好
204
00:06:46,600 --> 00:06:49,440
其实还真的是不太行
205
00:06:49,720 --> 00:06:51,000
来看看两个原因
206
00:06:51,480 --> 00:06:53,920
深度学习里面主要的数据
207
00:06:53,920 --> 00:06:55,080
大部分都是张量
208
00:06:55,280 --> 00:06:57,000
当然不能说标量和向量没有
209
00:06:57,280 --> 00:06:58,280
但大部分是张量
210
00:06:58,600 --> 00:06:59,480
而传统的编译器
211
00:06:59,640 --> 00:07:01,520
其实是不擅长对张量进行计算的
212
00:07:02,040 --> 00:07:03,760
更多的是对标量进行计算
213
00:07:04,040 --> 00:07:04,800
包括对向量
214
00:07:05,000 --> 00:07:06,640
可能说还不是说非常擅长
215
00:07:07,560 --> 00:07:09,360
第二个就是通用的编译器
216
00:07:09,360 --> 00:07:11,440
主要是针对通用的编程语言
217
00:07:11,680 --> 00:07:13,560
例如C++ Python Java
218
00:07:13,560 --> 00:07:15,000
这些通用的编程语言
219
00:07:15,320 --> 00:07:17,400
而很少缺乏领域特定的
220
00:07:17,400 --> 00:07:19,880
就domain specific language(DSL)的支持
221
00:07:20,160 --> 00:07:22,120
特别是针对神经网络
222
00:07:22,400 --> 00:07:24,040
还有相关的神经网络的优化
223
00:07:24,400 --> 00:07:26,440
所以会说AI编译器的后端
224
00:07:27,000 --> 00:07:29,320
不适合直接用传统的通用编译器
225
00:07:30,760 --> 00:07:32,440
下面来看看具体的一些
226
00:07:32,440 --> 00:07:33,520
算子的问题
227
00:07:33,520 --> 00:07:34,360
算子很重要
228
00:07:34,920 --> 00:07:36,600
算子的分类主要有两种
229
00:07:36,600 --> 00:07:39,000
一种是访存密集型
230
00:07:39,440 --> 00:07:40,880
可以看看下面这个图
231
00:07:41,000 --> 00:07:42,080
有一个向量A
232
00:07:42,080 --> 00:07:42,920
有个向量B
233
00:07:42,920 --> 00:07:44,240
那向量A和向量B
234
00:07:44,600 --> 00:07:46,520
都是从内存里面取出来的
235
00:07:46,920 --> 00:07:48,960
执行了一个ALU的乘法之后
236
00:07:49,411 --> 00:07:50,800
再放入cache里面
237
00:07:50,800 --> 00:07:51,920
或者内存里面
238
00:07:52,200 --> 00:07:54,000
那接着再从内存里面读出来
239
00:07:54,240 --> 00:07:55,040
再读下一次
240
00:07:55,400 --> 00:07:56,800
这种计算是大量的
241
00:07:56,800 --> 00:07:58,240
对内存进行访问
242
00:07:58,240 --> 00:08:00,400
所以叫做访存密集型
243
00:08:00,680 --> 00:08:02,400
特别是在神经网络里面
244
00:08:02,800 --> 00:08:04,640
大部分针对RNN
245
00:08:05,200 --> 00:08:06,320
循环神经网络
246
00:08:06,640 --> 00:08:08,800
它的计算密集度是比较低的
247
00:08:08,800 --> 00:08:12,880
那第二种分类就是计算密集型
248
00:08:12,880 --> 00:08:16,080
计算密集型 其实我觉得是非常好理解的
249
00:08:16,320 --> 00:08:17,840
我需要大量的计算
250
00:08:17,840 --> 00:08:19,560
不断的去算数的