forked from Infrasys-AI/AISystem
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy path04.srt
More file actions
772 lines (579 loc) · 15.3 KB
/
04.srt
File metadata and controls
772 lines (579 loc) · 15.3 KB
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
1
00:00:02,225 --> 00:00:07,450
哈喽大家晚上好,现在已经 12 点半了
2
00:00:07,450 --> 00:00:11,275
其实我本来想躺床上然后刷刷抖音就睡了
3
00:00:11,600 --> 00:00:15,000
想想还是不要刷抖音了,录一期吧
4
00:00:15,000 --> 00:00:20,000
今天晚上主要是来讲讲计算图的优化和执行
5
00:00:26,413 --> 00:00:28,575
对计算图的优化主要是编译优化
6
00:00:28,575 --> 00:00:32,000
编译优化的很多概念会留在后面来讲
7
00:00:32,000 --> 00:00:37,000
今天的重点主要是来讲讲计算图的调度和执行
8
00:00:37,000 --> 00:00:40,025
谈到图优化作用第一个概念
9
00:00:40,025 --> 00:00:44,000
看看右边的 AI 计算框架的这么一个组件图
10
00:00:44,000 --> 00:00:46,225
计算图的出现其实可以允许
11
00:00:46,225 --> 00:00:49,250
整个 AI 框架或者 AI 系统
12
00:00:49,250 --> 00:00:53,000
能够看到深度学习或者神经网络的全局定义
13
00:00:53,000 --> 00:00:57,400
也就是这个计算图其实是作为高层的 AI 一个表现
14
00:00:57,400 --> 00:01:02,000
把前端的具体的实现跟下层的优化把它隔绝起来
15
00:01:02,000 --> 00:01:06,000
所以这里面用不同的颜色把它区分下来
16
00:01:06,000 --> 00:01:10,175
实际上计算图的优化这一层是通过编译器去做的
17
00:01:10,175 --> 00:01:13,525
让看一下编译层或者图优化这个层
18
00:01:13,525 --> 00:01:15,000
具体做了哪些工作
19
00:01:15,000 --> 00:01:20,575
粉红色的这一层就是编译层或者图优化层
20
00:01:20,575 --> 00:01:23,725
上面的输入是计算图
21
00:01:23,725 --> 00:01:26,000
输出也是一个计算图
22
00:01:26,000 --> 00:01:28,650
区别就在于上面输入的这个计算图
23
00:01:28,650 --> 00:01:32,000
是没有经过优化的用户原始写出来的表达
24
00:01:32,950 --> 00:01:34,500
下面这个图呢
25
00:01:34,500 --> 00:01:37,262
经过图优化层然后去优化过的
26
00:01:37,262 --> 00:01:39,330
里面可能消除了一些部分节点
27
00:01:39,630 --> 00:01:41,075
中间的这些工作了
28
00:01:41,075 --> 00:01:43,750
会在编译优化系列给大家去讲讲
29
00:01:43,750 --> 00:01:46,525
这个编译优化层具体怎么实现的
30
00:01:46,525 --> 00:01:49,000
这里面呢,只是简单的提几个概念
31
00:01:49,000 --> 00:01:50,750
第一个就是常量折叠
32
00:01:50,750 --> 00:01:54,142
就是把一些常量把它合在一起
33
00:01:54,142 --> 00:01:56,175
例如 1 加 1 等于 2 的这些
34
00:01:56,175 --> 00:01:59,000
没有必要在计算的时候执行的时候才去算
35
00:01:59,000 --> 00:02:03,000
而是在编译的过程当中就把它算出来了
36
00:02:03,550 --> 00:02:06,075
第二个就是常量传播,
37
00:02:06,075 --> 00:02:10,000
那常量传播可能会跟常量折叠经常混合在一起
38
00:02:10,000 --> 00:02:11,775
还有一些算子融合
39
00:02:11,775 --> 00:02:14,000
把一些小的算子合成一些大算子
40
00:02:14,525 --> 00:02:17,000
那另外呢,针对表达式呢
41
00:02:17,000 --> 00:02:20,000
还有一些表达式的转换表达式的替换
42
00:02:20,000 --> 00:02:22,625
例如 X 乘以 X 乘以 X
43
00:02:22,625 --> 00:02:26,000
可能直接表示成 X 的三次方
44
00:02:26,000 --> 00:02:30,000
最后呢,可能还会有一些公共表达式的消除
45
00:02:30,000 --> 00:02:32,475
那这个呢,就是代码层面的
46
00:02:32,475 --> 00:02:34,075
这个是算子层面的
47
00:02:34,075 --> 00:02:36,000
那这些呢,就是图层面的
48
00:02:36,000 --> 00:02:38,175
所以呢,图优化图编译层
49
00:02:38,175 --> 00:02:41,000
会在不同的内容方面去进行优化
50
00:02:41,000 --> 00:02:44,775
下面呢,回到今天的一个主要的内容
51
00:02:44,775 --> 00:02:47,725
就是计算图的调度和执行
52
00:02:47,975 --> 00:02:49,925
公式,还是那条公式
53
00:02:49,925 --> 00:02:52,000
这个呢,就是计算图
54
00:02:52,000 --> 00:02:56,250
然后呢,AI 框架呢,会根据计算图的依赖关系
55
00:02:56,250 --> 00:02:59,000
依次去调度将要运行的一些代码
56
00:02:59,000 --> 00:03:00,525
例如我首先执行一个 Log
57
00:03:00,525 --> 00:03:03,000
然后执行 Mul,然后 Sin,Add,Sub
58
00:03:03,000 --> 00:03:06,000
接着呢,再执行一些反向的操作
59
00:03:06,000 --> 00:03:09,000
那执行之前呢,不是直接执行的
60
00:03:09,000 --> 00:03:11,775
通过分析计算图的依赖关系
61
00:03:11,775 --> 00:03:15,000
然后丢到一个算子的执行列表里面
62
00:03:15,000 --> 00:03:17,550
然后呢,NPU 或者 GPU 呢
63
00:03:17,550 --> 00:03:19,800
就会根据算子列表
64
00:03:19,800 --> 00:03:22,000
然后足够的去执行,给出结果
65
00:03:22,000 --> 00:03:26,000
那这个呢,就是最简单的,最原始的调度执行
66
00:03:26,000 --> 00:03:28,675
那这个呢,就是刚才那条公式
67
00:03:28,675 --> 00:03:31,000
万年不变的一条公式的时间流图
68
00:03:31,000 --> 00:03:34,450
首先去执行一个乘,然后 Log,Sin,加减
69
00:03:34,450 --> 00:03:36,000
接着呢,去执行反向的
70
00:03:36,000 --> 00:03:39,500
那可能反向求完导之后就不一定是这个呀
71
00:03:39,500 --> 00:03:42,000
Sin 的反向可能是 Cos
72
00:03:42,000 --> 00:03:44,825
那在 AI 框架的设备调度里面呢
73
00:03:44,825 --> 00:03:47,825
虽然是单算子调度或者单机器调度
74
00:03:47,825 --> 00:03:50,000
但是呢,也没有这么简单
75
00:03:50,000 --> 00:03:53,000
会去分析算子之间的依赖关系
76
00:03:53,000 --> 00:03:58,000
首先 AI 框架呢,会去分析算子之间的一个依赖关系
77
00:03:58,000 --> 00:04:02,000
根据数据流图,找到一些独立的算子的节点
78
00:04:02,000 --> 00:04:04,125
要是它独立,例如 X1 跟 x2
79
00:04:04,125 --> 00:04:06,000
其实它们两个算子是独立的
80
00:04:06,000 --> 00:04:08,000
x1 可以先算,x2 可以后算
81
00:04:08,000 --> 00:04:10,075
如果两者之间没有关系
82
00:04:10,075 --> 00:04:13,000
它们可能就会进入到并发执行的对列
83
00:04:13,000 --> 00:04:15,525
然后呢,机器就会根据这个对列
84
00:04:15,525 --> 00:04:18,000
然后放在不同的线程池里面去执行
85
00:04:18,000 --> 00:04:21,000
这个时候就很好的提高并行效率
86
00:04:21,000 --> 00:04:24,500
因为都知道 GPU,NPU
87
00:04:24,500 --> 00:04:26,475
其实不仅仅有一个核
88
00:04:26,475 --> 00:04:28,700
而是有很多个计算单元
89
00:04:28,700 --> 00:04:31,000
很多个计算核来去组成的
90
00:04:31,000 --> 00:04:34,325
单单简单的按照最原始的方式
91
00:04:34,325 --> 00:04:36,150
一个一个算子排列
92
00:04:36,150 --> 00:04:38,000
这种调度方式是很慢的
93
00:04:38,000 --> 00:04:41,500
所以有了计算图之后呢
94
00:04:41,500 --> 00:04:44,000
就会对图层进行优化分析
95
00:04:44,252 --> 00:04:46,425
让 AI 框架执行的更快
96
00:04:46,425 --> 00:04:48,000
让训练更快
97
00:04:51,000 --> 00:04:55,175
假设现在有很多华为昇腾 Atlas 的设备
98
00:04:55,175 --> 00:04:58,650
这个时候就需要对计算图进行切分
99
00:04:58,650 --> 00:05:00,000
还有多设备执行
100
00:05:00,000 --> 00:05:03,000
可是这么去执行就变得非常复杂了
101
00:05:03,000 --> 00:05:06,775
首先可能会考虑对计算图进行切分
102
00:05:06,775 --> 00:05:11,100
就是会把一个大的网络模型切分成一些小图
103
00:05:11,100 --> 00:05:14,000
然后放在不同的设备上面去执行
104
00:05:14,000 --> 00:05:18,000
每一个设备都有计算图的一部分
105
00:05:18,000 --> 00:05:21,200
既然把计算图进行切分了
106
00:05:21,200 --> 00:05:24,625
那计算图跟计算图之间就需要通讯
107
00:05:24,625 --> 00:05:27,000
需要对数据进行聚合
108
00:05:28,000 --> 00:05:33,050
这个时候就涉及到跨设备跨子图的一个数据传输
109
00:05:33,050 --> 00:05:38,000
可能数据传输的效率就会是制约整个计算的性能
110
00:05:38,000 --> 00:05:40,200
那为了解决这些问题
111
00:05:40,200 --> 00:05:44,000
可能又会引起了多种的调度和执行的策略
112
00:05:44,000 --> 00:05:48,000
左边的这个图就是 GoogleNet Inception 这个网络模型
113
00:05:48,000 --> 00:05:51,900
假设我现在有四台 Atlas 的设备
114
00:05:51,900 --> 00:05:53,700
或者叫做 4 张卡
115
00:05:53,700 --> 00:05:56,100
4 张 NPU 或者 GPU
116
00:05:56,100 --> 00:06:01,000
那可能第一个 1x1 的卷积会放在这一个设备去执行
117
00:06:01,000 --> 00:06:07,000
第二个 3x3 的卷积会同步的放在第二个设备执行
118
00:06:07,000 --> 00:06:09,225
同样的后面 5x5 的卷积
119
00:06:09,225 --> 00:06:13,000
还有 3x3 的卷积都放在不同的设备执行
120
00:06:13,000 --> 00:06:16,875
这个只是最简单的放在不同的设备执行
121
00:06:16,875 --> 00:06:22,000
但是一旦放在不同的设备就会涉及到一个多种的调度模式
122
00:06:22,000 --> 00:06:24,325
这个就是三种调度模式
123
00:06:24,325 --> 00:06:26,700
简单的来讲讲有哪几种
124
00:06:26,700 --> 00:06:29,000
通常肯定是越贪心越好的
125
00:06:29,000 --> 00:06:32,375
最简单的就是我首先虽然有很多种设备
126
00:06:32,375 --> 00:06:34,725
但是我在一个设备上面运行
127
00:06:34,725 --> 00:06:37,350
这个卷积在另外一个设备运行
128
00:06:37,350 --> 00:06:40,000
这个卷积又在另外一个设备运行
129
00:06:40,000 --> 00:06:41,950
这种就是最原始的串行
130
00:06:41,950 --> 00:06:45,000
现在没有人这么傻会这么去串行去做的
131
00:06:45,000 --> 00:06:49,325
如果真的是设计出这种傻逼的操作之后
132
00:06:49,325 --> 00:06:54,000
像我这样的工程师肯定第一时间被老板炒
133
00:06:54,000 --> 00:06:56,150
那第二个就是并行调度
134
00:06:56,150 --> 00:06:59,590
我第一个卷积在设备 1 上面去执行,
135
00:06:59,590 --> 00:07:01,850
第二个卷积在设备 2 上面去执行
136
00:07:01,850 --> 00:07:04,000
那我的时间可能是差不多的
137
00:07:04,000 --> 00:07:07,425
最后把在不同设备上面
138
00:07:07,425 --> 00:07:12,900
去运行的结果 concat 到一起,最终输出
139
00:07:12,900 --> 00:07:14,875
那这种方式会比第一种方式更优
140
00:07:14,875 --> 00:07:17,000
但肯定希望三种设备所有的都同时开启
141
00:07:17,000 --> 00:07:21,875
那这个时候就可能设计到通讯的等待、通讯的市集
142
00:07:21,875 --> 00:07:24,000
这个就是贪心调度
143
00:07:24,000 --> 00:07:25,300
所以一般来说
144
00:07:25,300 --> 00:07:28,275
涉及到跨图跨设备,那就变得非常复杂
145
00:07:28,275 --> 00:07:31,850
这个会在后面的大规模分布式并行里面去讲讲
146
00:07:31,850 --> 00:07:37,000
具体 MindSpore、TensorFlow 和 PyTorch 是怎么实现
147
00:07:38,625 --> 00:07:42,400
那下面来看看具体的一个简单的例子
148
00:07:42,400 --> 00:07:46,775
这个 Inception 模块就有三个输入到不同的卷积
149
00:07:46,775 --> 00:07:50,000
最后汇集起来 concat 到一起,然后给输出的
150
00:07:50,575 --> 00:07:53,350
现在分在两个不同的设备
151
00:07:53,350 --> 00:07:58,725
一个叫做华为 Atlas 0, 第二个叫做华为 Atlas 1
152
00:07:58,725 --> 00:08:00,575
我又在卖广告了。
153
00:08:03,000 --> 00:08:06,325
其实这个视频跟公司没有关系
154
00:08:06,325 --> 00:08:09,250
是我私人的时间去录制的
155
00:08:09,250 --> 00:08:12,000
现在的时间接近凌晨一点钟
156
00:08:13,000 --> 00:08:15,925
接着来看看数据是怎么切分的
157
00:08:15,925 --> 00:08:19,200
从刚才的 Inception 图里面可以看到
158
00:08:19,200 --> 00:08:21,050
假设我这么去切分
159
00:08:21,050 --> 00:08:25,000
我可能去把两个卷积放在第一台设备上面去执行
160
00:08:25,000 --> 00:08:32,025
另外两个卷积放在另外一台设备上面去执行
161
00:08:32,025 --> 00:08:36,375
中间我可能会有两个通讯的原语或者通讯的算子
162
00:08:37,025 --> 00:08:39,275
一个是发送的,一个是接收的
163
00:08:39,275 --> 00:08:43,000
最后再 concat 到其中一台服务器上面去做聚合
164
00:08:43,000 --> 00:08:47,475
这种方式可能会用 Send, Reserve
165
00:08:47,475 --> 00:08:50,150
这些算子去代替数据传输
166
00:08:50,150 --> 00:08:53,475
也可能直接通过 HCCL 或者 NCCL
167
00:08:53,475 --> 00:08:57,000
这种通讯原语或者通讯算子进行一个数据传输
168
00:08:57,000 --> 00:09:02,100
但实际上一旦涉及到夸 4 倍的通讯就会引起大量的问题
169
00:09:02,100 --> 00:09:04,775
实际上要做好计算图的切分
170
00:09:04,775 --> 00:09:07,900
并且把这些子图映射到多个设备里面
171
00:09:07,900 --> 00:09:11,000
是一个非常复杂的组合优化问题
172
00:09:11,000 --> 00:09:13,525
需要在代价模型里面
173
00:09:13,525 --> 00:09:18,750
去找到跨设备通讯消耗时间最短的每个计算单元
174
00:09:18,750 --> 00:09:23,000
然后看一下怎么随着输入输出的大小的变化而变化
175
00:09:23,000 --> 00:09:25,675
最后以数据流依赖作为约束
176
00:09:25,675 --> 00:09:27,075
均衡并行执行
177
00:09:27,075 --> 00:09:30,150
还有数据通信两者之间的关系
178
00:09:30,150 --> 00:09:33,000
去找到一个最好的 balance
179
00:09:33,000 --> 00:09:38,175
这个时候我就需要考虑到我的计算图是怎么切分的
180
00:09:38,175 --> 00:09:43,000
应该怎么切才能够使得我这个组合优化问题效率更高
181
00:09:44,000 --> 00:09:46,650
好了,今天的内容比较简单
182
00:09:46,650 --> 00:09:51,450
主要了解了对于计算图做了一些编译优化的手段
183
00:09:51,450 --> 00:09:54,000
才能使得图执行的更快
184
00:09:54,000 --> 00:09:59,000
这个编译优化手段会在编译体系的系列里面去详细的展开
185
00:09:59,000 --> 00:10:03,200
第二个就是了解了计算图最基础的调度执行模式
186
00:10:03,200 --> 00:10:05,375
也就是单算子的调度模式
187
00:10:05,375 --> 00:10:08,000
还有优化后的端线程的调度模式
188
00:10:08,000 --> 00:10:10,100
最后了解了计算图
189
00:10:10,100 --> 00:10:13,350
在多设备上进行图切分和多设备执行
190
00:10:13,350 --> 00:10:15,775
这一个的详细展开也会
191
00:10:15,775 --> 00:10:19,000
在大规模分布式并行里面去详细的展开
192
00:10:19,000 --> 00:10:22,000
那个内容可能会更有意思
193
00:10:24,000 --> 00:10:26,000
好了,谢谢各位,拜拜。