forked from chenzomi12/AISystem
-
Notifications
You must be signed in to change notification settings - Fork 0
/
04.srt
1984 lines (1488 loc) · 31 KB
/
04.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,000 --> 00:00:05,400
字幕生成:qiaokai 字幕校对:mkwei
2
00:00:06,333 --> 00:00:06,933
哈喽
3
00:00:06,933 --> 00:00:08,666
大家好我是ZOMI
4
00:00:08,666 --> 00:00:09,866
今天来到
5
00:00:09,866 --> 00:00:11,966
AI编译器系列里面的前端优化
6
00:00:11,966 --> 00:00:14,466
来讲讲数据布局转换
7
00:00:15,866 --> 00:00:17,133
在之前的内容里面呢
8
00:00:17,133 --> 00:00:18,966
讲了一个图层的IR
9
00:00:18,966 --> 00:00:19,999
就是计算图
10
00:00:20,000 --> 00:00:22,933
怎么转换成AI编译器的前端的输入
11
00:00:22,966 --> 00:00:24,699
接着去了解了一下
12
00:00:24,700 --> 00:00:26,866
算子融合的一个基础的原理
13
00:00:26,866 --> 00:00:28,266
和算子融合的方式
14
00:00:28,300 --> 00:00:31,400
今天呢来讲讲数据布局的转换
15
00:00:31,400 --> 00:00:33,800
其实很多人对数据布局其实
16
00:00:33,800 --> 00:00:35,166
不是说非常的敏感
17
00:00:35,166 --> 00:00:36,299
但是数据布局呢
18
00:00:36,300 --> 00:00:38,100
对AI编译器来说是
19
00:00:38,100 --> 00:00:40,000
非常重要的一个环节
20
00:00:40,133 --> 00:00:43,699
数据布局主要是layout transformation
21
00:00:43,766 --> 00:00:44,299
然后呢
22
00:00:44,300 --> 00:00:46,666
今天会分开几个内容去介绍的
23
00:00:47,000 --> 00:00:48,666
如果十来分钟介绍不完
24
00:00:48,666 --> 00:00:50,499
会拆开两个内容
25
00:00:50,500 --> 00:00:51,400
那首先看看
26
00:00:51,400 --> 00:00:53,400
今天要给大家汇报
27
00:00:53,400 --> 00:00:54,333
哪些知识点
28
00:00:54,333 --> 00:00:57,133
首先第一个就是数据内存的排布
29
00:00:57,133 --> 00:00:57,599
第二个呢
30
00:00:57,600 --> 00:00:59,566
去看看张量的一个数据
31
00:00:59,566 --> 00:01:01,333
具体内存是怎么排布的
32
00:01:01,500 --> 00:01:01,966
再往下呢
33
00:01:01,966 --> 00:01:03,766
会去看看NCHW
34
00:01:03,800 --> 00:01:06,166
和NHWC之间的数据排布
35
00:01:06,166 --> 00:01:07,499
具体有什么作用
36
00:01:07,500 --> 00:01:08,533
有什么不同
37
00:01:08,533 --> 00:01:09,566
对于硬件来说
38
00:01:09,566 --> 00:01:11,999
更青睐于采用哪种方式
39
00:01:12,366 --> 00:01:14,999
往下就是自己华为昇腾的产品
40
00:01:15,000 --> 00:01:17,466
去看看华为昇腾的一个数据
41
00:01:17,466 --> 00:01:18,499
布局的排布
42
00:01:18,500 --> 00:01:19,733
到底是怎么样的
43
00:01:19,800 --> 00:01:23,966
又怎么如何跟NCHW或者NHWC进行融合
44
00:01:24,100 --> 00:01:24,666
最后呢
45
00:01:24,666 --> 00:01:27,933
去看看AI编译器的数据布局转换
46
00:01:27,933 --> 00:01:29,366
是怎么做优化
47
00:01:30,333 --> 00:01:30,766
现在呢
48
00:01:30,766 --> 00:01:33,933
回头来看看在哪个位置
49
00:01:34,000 --> 00:01:37,133
前端把Python的代码呢进行解析
50
00:01:37,133 --> 00:01:38,466
那这个解析的过程呢
51
00:01:38,466 --> 00:01:41,333
是通过AI框架去实现的
52
00:01:41,366 --> 00:01:43,533
解析完之后得到一个计算图
53
00:01:43,533 --> 00:01:46,333
那计算图呢就传给AI编译器的
54
00:01:46,533 --> 00:01:48,866
第一层图层的IR的优化
55
00:01:48,866 --> 00:01:52,066
现在在这个地方数据布局转换
56
00:01:52,066 --> 00:01:53,499
作为图层IR
57
00:01:53,500 --> 00:01:55,333
前端优化的一个pass
58
00:01:56,900 --> 00:01:57,400
接下来呢
59
00:01:57,400 --> 00:01:59,000
看一下第一个内容
60
00:01:59,000 --> 00:02:01,200
数据内存的排布
61
00:02:02,400 --> 00:02:03,600
ZOMI老师你好
62
00:02:03,600 --> 00:02:06,166
我想问一下什么是内存对齐啊
63
00:02:06,166 --> 00:02:09,133
为什么要对内存进行对齐呢
64
00:02:10,000 --> 00:02:12,266
哎这位同学问的问题非常好啊
65
00:02:12,266 --> 00:02:14,199
这也是第一个内容
66
00:02:14,366 --> 00:02:15,066
哈哈哈
67
00:02:15,066 --> 00:02:17,166
还是我自己问自己答的
68
00:02:17,166 --> 00:02:19,766
第一个内容呢就是讲数据内存的排布
69
00:02:19,933 --> 00:02:21,333
首先要了解一个概念
70
00:02:21,333 --> 00:02:22,799
就是内存的对齐
71
00:02:22,800 --> 00:02:26,000
和数据在内存里面的位置是相关的
72
00:02:26,000 --> 00:02:28,533
那现在看看左边的这个图
73
00:02:28,900 --> 00:02:30,600
这里面呢是memory
74
00:02:30,600 --> 00:02:32,266
就是内存的地址
75
00:02:32,266 --> 00:02:33,666
这些存的都是
76
00:02:33,666 --> 00:02:35,199
内存的一个具体的地址
77
00:02:35,300 --> 00:02:38,166
而右边的这个呢就是实际的数据
78
00:02:38,166 --> 00:02:40,666
数据呢是存放在内存
79
00:02:40,700 --> 00:02:42,166
某个地址里面的
80
00:02:42,333 --> 00:02:45,399
而内存呢是以字节为单位进行存储
81
00:02:45,400 --> 00:02:46,566
如果一个变量
82
00:02:46,566 --> 00:02:48,566
或者一个数据的内存的地址呢
83
00:02:48,566 --> 00:02:50,533
刚好等于它的长度的倍数
84
00:02:50,533 --> 00:02:52,999
那这个呢就称为自然对齐
85
00:02:53,133 --> 00:02:53,866
理论上呢
86
00:02:53,866 --> 00:02:56,533
其实可以从任意地址开始进行
87
00:02:56,533 --> 00:02:57,999
读取和写入的
88
00:02:58,300 --> 00:03:00,066
如果数据内存没有对齐呢
89
00:03:00,066 --> 00:03:01,266
可能就比较麻烦
90
00:03:01,266 --> 00:03:02,599
读取数据的时候呢
91
00:03:02,600 --> 00:03:03,600
就没有那么方便
92
00:03:03,600 --> 00:03:05,766
要对数据呢进行一个偏移再读取
93
00:03:05,766 --> 00:03:06,599
然后再合并
94
00:03:07,200 --> 00:03:10,066
尽管现代的内存呢是以字节为单位的
95
00:03:10,066 --> 00:03:12,066
但是呢现在的处理器呢
96
00:03:12,066 --> 00:03:14,799
是以字为单位进行一个读写和访问的
97
00:03:14,800 --> 00:03:16,200
CPU啊
98
00:03:16,200 --> 00:03:18,400
或者不管是Inter还是arm的CPU
99
00:03:18,500 --> 00:03:20,933
还是按字节块的方式来去读取的
100
00:03:20,933 --> 00:03:23,099
而一般有几种读取方式
101
00:03:23,100 --> 00:03:24,733
就是以字节2
102
00:03:24,933 --> 00:03:28,666
4 8 16这种字节的方式为粒度呢
103
00:03:28,666 --> 00:03:30,133
进行内存的读写
104
00:03:30,133 --> 00:03:31,899
既然CPU和系统呢
105
00:03:31,900 --> 00:03:34,466
是根据这些字节为单位进行读取
106
00:03:34,700 --> 00:03:37,000
所以呢尽可能的把数据
107
00:03:37,066 --> 00:03:39,299
根据这个单位进行对齐
108
00:03:39,300 --> 00:03:41,666
才能够高效的去利用硬件
109
00:03:41,666 --> 00:03:44,166
充分的发挥硬件的性能
110
00:03:44,200 --> 00:03:45,366
现在呢来看看
111
00:03:45,366 --> 00:03:48,499
假设数据内存没有对齐
112
00:03:48,500 --> 00:03:50,666
会产生一个什么样的情况
113
00:03:50,766 --> 00:03:52,066
那下面这个图呢
114
00:03:52,133 --> 00:03:55,099
以4字节存储的粒度为单位
115
00:03:55,100 --> 00:03:56,200
读取一个int
116
00:03:56,200 --> 00:03:57,100
一个变量
117
00:03:57,333 --> 00:04:00,766
int呢有4个字节32比特
118
00:04:00,766 --> 00:04:01,599
处理器去读取的时候呢
119
00:04:01,600 --> 00:04:04,366
会默认从4的倍数的地址开始进行
120
00:04:04,366 --> 00:04:08,599
读取假设我这个位置的地址呢是0X0000
121
00:04:08,900 --> 00:04:12,166
这个位置的地址呢可能是0X0004
122
00:04:12,333 --> 00:04:14,499
假设现在的数据存储呢
123
00:04:14,500 --> 00:04:16,133
是没有以四字节为单位
124
00:04:16,133 --> 00:04:17,199
进行一个存储的
125
00:04:17,266 --> 00:04:18,766
现在去读取的时候呢
126
00:04:18,766 --> 00:04:22,366
先读取上面红色的这块的前三个Byte
127
00:04:22,500 --> 00:04:23,200
然后呢
128
00:04:23,200 --> 00:04:25,400
再读取这蓝色的这一块的
129
00:04:25,400 --> 00:04:26,533
第一个Low Byte
130
00:04:26,533 --> 00:04:29,133
就是第一个最低的位置地址
131
00:04:29,133 --> 00:04:31,399
就是我红色的这个位置
132
00:04:31,533 --> 00:04:34,499
这个时候呢我就需要访问两次内存的
133
00:04:34,500 --> 00:04:37,333
第一次呢就是读取红色的高位的地址
134
00:04:37,333 --> 00:04:40,166
第二次呢就是读取蓝色的低位的地址
135
00:04:40,400 --> 00:04:41,600
读取完之后呢
136
00:04:41,600 --> 00:04:43,366
第一次从0地址读取
137
00:04:43,366 --> 00:04:45,866
然后把首个字节呢剔除出来
138
00:04:45,866 --> 00:04:49,099
第二次呢从4地址开始读取只读取
139
00:04:49,533 --> 00:04:50,799
首个字节
140
00:04:50,800 --> 00:04:53,733
最后呢把这两块地址呢合并起来
141
00:04:53,800 --> 00:04:54,800
变成一个
142
00:04:54,800 --> 00:04:56,600
int 32位就取一个数
143
00:04:56,733 --> 00:04:58,666
假设现在只取了一个1,000的数
144
00:04:58,666 --> 00:05:00,933
但是呢读内存要读两次
145
00:05:00,933 --> 00:05:03,499
这是非常耗费硬件的资源的
146
00:05:03,800 --> 00:05:05,166
刚才1,000这个数呢
147
00:05:05,166 --> 00:05:07,966
已经存在红色这块地址
148
00:05:07,966 --> 00:05:08,866
这种情况呢
149
00:05:08,866 --> 00:05:10,733
叫做做了一个数据
150
00:05:10,733 --> 00:05:12,966
跟内存一个严格对齐
151
00:05:13,333 --> 00:05:16,699
读取的时候呢起始位置作为4的倍数
152
00:05:16,700 --> 00:05:18,600
然后只需要进行一次读取
153
00:05:18,600 --> 00:05:20,000
就可以从memory
154
00:05:20,000 --> 00:05:21,933
然后把数据搬到一个寄存器
155
00:05:21,933 --> 00:05:22,533
里面了
156
00:05:22,533 --> 00:05:24,366
最后呢给SLA进行计算
157
00:05:25,566 --> 00:05:27,699
以字节的大小为粒度呢进行内存访问
158
00:05:27,700 --> 00:05:28,733
其实有两个好处
159
00:05:28,733 --> 00:05:30,733
第一个呢就是提升访问速率
160
00:05:30,733 --> 00:05:32,066
为什么提升访问速率
161
00:05:32,066 --> 00:05:33,699
刚才其实已经用一个
162
00:05:33,700 --> 00:05:34,933
简单的例子讲了
163
00:05:34,933 --> 00:05:35,333
第二个呢
164
00:05:35,333 --> 00:05:37,766
就是保存数据的一个原子性
165
00:05:37,933 --> 00:05:40,599
现在简单的来看看两个的好处
166
00:05:40,600 --> 00:05:41,900
现在CPU呢
167
00:05:41,900 --> 00:05:43,966
大部分都有多个高级的缓存呢
168
00:05:43,966 --> 00:05:44,399
数据呢
169
00:05:44,400 --> 00:05:46,866
必须通过这些高级缓存去读取数据的
170
00:05:46,866 --> 00:05:49,366
而以字节大小粒度呢进行内存访问呢
171
00:05:49,366 --> 00:05:52,166
可以整体提升CPU的吞吐量
172
00:05:52,166 --> 00:05:54,933
那第二点就是原子性的问题
173
00:05:55,066 --> 00:05:55,466
CPU呢
174
00:05:55,466 --> 00:05:57,666
可以在一个对齐的内存上面进行操作
175
00:05:57,666 --> 00:05:58,733
这意味着没有
176
00:05:58,733 --> 00:06:00,933
指令可以中断访问操作
177
00:06:00,933 --> 00:06:02,366
对于很多没有锁的数据
178
00:06:02,366 --> 00:06:03,699
或者数据结构来说呢
179
00:06:03,700 --> 00:06:05,533
可以提升并发的正确性
180
00:06:05,533 --> 00:06:07,066
那这个就是两个好处
181
00:06:08,066 --> 00:06:10,166
接下来呢回到AI的概念
182
00:06:10,166 --> 00:06:10,999
就是张量
183
00:06:11,000 --> 00:06:12,766
张量的数据呢又是如何布局
184
00:06:12,766 --> 00:06:13,933
刚才只是讲了
185
00:06:13,933 --> 00:06:15,333
在普通的X86上面
186
00:06:15,333 --> 00:06:17,299
数据是怎么进行一个存储
187
00:06:17,300 --> 00:06:19,366
的数据的存储方式呢
188
00:06:19,366 --> 00:06:20,499
是根据数据在
189
00:06:20,500 --> 00:06:22,100
主存里面的存储的方式
190
00:06:22,100 --> 00:06:23,500
之上作为基础的
191
00:06:25,733 --> 00:06:28,133
现在来看看张量和内存的
192
00:06:28,133 --> 00:06:29,099
排布的方式
193
00:06:29,100 --> 00:06:31,100
那张量呢是一个多维的数组
194
00:06:31,100 --> 00:06:33,366
先看看简单的一个数呢
195
00:06:33,366 --> 00:06:34,499
叫做标量
196
00:06:34,500 --> 00:06:35,400
他只有一个数
197
00:06:35,400 --> 00:06:36,900
而有多个数的时候呢
198
00:06:36,900 --> 00:06:38,000
叫做向量
199
00:06:38,000 --> 00:06:39,500
就是一维的张量
200
00:06:39,600 --> 00:06:40,566
如果数据呢
201
00:06:40,566 --> 00:06:41,666
是一个矩阵的时候呢
202
00:06:41,666 --> 00:06:43,133
叫做二维的张量
203
00:06:43,133 --> 00:06:44,333
当数据
204
00:06:44,333 --> 00:06:46,299
假设像这样一张图片
205
00:06:46,300 --> 00:06:49,866
那图片呢有长宽高还有一个通道数RGB
206
00:06:49,900 --> 00:06:52,333
那这个时候呢就会变成三维的张量
207
00:06:52,500 --> 00:06:54,600
当然了在神经网络处理的时候呢
208
00:06:54,666 --> 00:06:56,133
会有一个Batch Size
209
00:06:56,133 --> 00:06:57,999
作为批数据处理的方式
210
00:06:58,000 --> 00:07:00,266
那这个时候呢就变成四维的张量了
211
00:07:00,466 --> 00:07:01,533
而作为0维张量
212
00:07:01,533 --> 00:07:02,799
单单一个数呢
213
00:07:02,800 --> 00:07:04,600
以字节为单位进行存储
214
00:07:04,700 --> 00:07:06,300
向量里面每一个元素呢
215
00:07:06,300 --> 00:07:08,200
都是按字节为单位进行存储
216
00:07:08,366 --> 00:07:10,266
但是当维度越来越高
217
00:07:10,266 --> 00:07:11,866
内存数据地址呢
218
00:07:11,866 --> 00:07:13,166
是按列进行排布的
219
00:07:13,166 --> 00:07:14,566
所以存储1维张量的时候
220
00:07:14,566 --> 00:07:15,999
大家比较好理解
221
00:07:16,000 --> 00:07:17,766
这里面 5呢我存在一个地址
222
00:07:17,766 --> 00:07:18,699
4存在一个地址
223
00:07:18,700 --> 00:07:20,766
3存在一个地址2存在一个地址
224
00:07:20,766 --> 00:07:22,299
但是呢当矩阵的时候
225
00:07:22,300 --> 00:07:23,166
可能
226
00:07:23,466 --> 00:07:26,133
1存在一个地址里面不断的往下排
227
00:07:26,133 --> 00:07:28,599
2存在一个地址里面不断的往下排
228
00:07:28,600 --> 00:07:30,100
3也是但是
229
00:07:30,100 --> 00:07:32,500
张量的维度越来越高的时候
230
00:07:32,500 --> 00:07:33,966
是先存列了
231
00:07:34,133 --> 00:07:35,333
还是先存行呢
232
00:07:35,366 --> 00:07:38,333
还是先存channel的数量呢
233
00:07:38,333 --> 00:07:40,266
如果再加一个维度的时候
234
00:07:40,266 --> 00:07:41,733
数据应该怎么存呢
235
00:07:41,733 --> 00:07:42,199
这个时候
236
00:07:42,200 --> 00:07:43,333
就引起张量
237
00:07:43,333 --> 00:07:45,066
里内存排布的一个问题啦
238
00:07:46,933 --> 00:07:47,599
现在呢
239
00:07:47,600 --> 00:07:49,066
先以一个简单形状的
240
00:07:49,066 --> 00:07:51,133
3*2*2的一个3维张量
241
00:07:51,133 --> 00:07:53,399
进行一个存储排布的一个讲解
242
00:07:53,400 --> 00:07:54,600
或者作为一个例子
243
00:07:54,766 --> 00:07:57,933
假设先按行优先进行数据排布
244
00:07:57,966 --> 00:08:00,666
红色的这个呢叫做按行进行排布
245
00:08:00,666 --> 00:08:03,366
现在是一个3*2*2的3维张量
246
00:08:03,366 --> 00:08:05,099
那会以行进行排布
247
00:08:05,100 --> 00:08:06,900
先把红色的排起来
248
00:08:06,900 --> 00:08:08,900
然后再把橙色的排起来
249
00:08:08,900 --> 00:08:11,466
接着呢再排绿色的这一个位置
250
00:08:11,466 --> 00:08:14,499
最后呢再排底下蓝色的这个位置