昇腾社区首页
EN
注册

同步等待

本节介绍Device、Stream、Event、Notify在异步场景下的使用示例及关键接口。

同步机制

同步机制包含以下几种:

Event的同步等待示例代码

调用aclrtSynchronizeEvent接口,阻塞应用程序运行,等待Event完成。

Stream内任务的同步等待示例代码

调用aclrtSynchronizeStream接口,阻塞应用程序运行,直到指定Stream中的所有任务都完成。

Stream间任务的同步等待示例代码

支持以下方式:

Noitfy与Event差别在于,等到Wait Notify完成后,Notify状态会自动重置,因此一个Record Notify任务只能通知一个Wait Notify任务;而Wait Event并不会自动重置Event状态,因此一个Record Event任务可以做到通知一个或多个Wait Event任务。

Device的同步等待示例代码

调用aclrtSynchronizeDevice接口,阻塞应用程序运行,直到正在运算中的Device完成运算。多Device场景下,调用该接口等待的是当前Context对应的Device。

Event的同步等待

调用接口后,需增加异常处理的分支,并记录报错日志、提示日志,此处不一一列举。以下是关键步骤的代码示例,不可以直接拷贝编译运行,仅供参考。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
#include "acl/acl.h"
// ......
// 创建一个Event
aclrtEvent event;
aclrtCreateEventExWithFlag(&event, ACL_EVENT_CAPTURE_STREAM_PROGRESS);

// 显式创建一个Stream
aclrtStream stream;
aclrtCreateStream(&stream);

// stream末尾添加了一个event
aclrtRecordEvent(event, stream);

// 阻塞应用程序运行,等待event发生,也就是stream执行完成
// stream完成后产生event,唤醒执行应用程序的控制流,开始执行程序
aclrtSynchronizeEvent(event);

// 显式销毁资源
aclrtDestroyStream(stream);
aclrtDestroyEvent(event);
// ......

Stream内任务的同步等待

调用接口后,需增加异常处理的分支,并记录报错日志、提示日志,此处不一一列举。以下是关键步骤的代码示例,不可以直接拷贝编译运行,仅供参考。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
#include "acl/acl.h"
// ......
// 显式创建一个Stream
aclrtStream stream;
aclrtCreateStream(&stream);
// 调用触发任务的接口,传入stream参数
aclrtMemcpyAsync(dstPtr, dstSize, srcPtr, srcSize, ACL_MEMCPY_HOST_TO_DEVICE, stream);
// 调用aclrtSynchronizeStream接口,阻塞应用程序运行,直到指定Stream中的所有任务都完成。
aclrtSynchronizeStream(stream);

// Stream使用结束后,显式销毁Stream
aclrtDestroyStream(stream);
// ......

Stream间任务的同步等待(通过Event实现)

多Stream之间任务的同步等待可以利用Event实现,例如,若stream2的任务依赖stream1的任务,想保证stream1中的任务先完成,这时可创建一个Event,调用aclrtRecordEvent接口将Event插入到stream1中(通常称为Record Event任务),调用aclrtStreamWaitEvent接口在stream2中插入一个等待Event完成的任务(通常称为Wait Event任务)。

图1 同步等待流程_多Stream场景

上图中的模型加载与执行的流程请参见模型管理,算子加载与执行的流程请参见单算子调用

调用接口后,需增加异常处理的分支,并记录报错日志、提示日志,此处不一一列举。以下是关键步骤的代码示例,不可以直接拷贝编译运行,仅供参考。

 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
#include "acl/acl.h"
// ......
// 创建一个Event
aclrtEvent event;
aclrtCreateEventExWithFlag(&event, ACL_EVENT_SYNC);

// 创建stream1
aclrtStream s1;
aclrtCreateStream(&s1);

// 创建stream2
aclrtStream s2;
aclrtCreateStream(&s2);

// 在s1末尾添加了一个event
aclrtRecordEvent(event, s1);

// 阻塞s2运行,直到指定event发生,也就是s1执行完成
// s1完成后,唤醒s2,继续执行s2的任务
aclrtStreamWaitEvent(s2, event);
aclrtResetEvent(event, s2);

aclrtSynchronizeStream(s1);
aclrtSynchronizeStream(s2);

// 显式销毁资源
aclrtDestroyStream(s2);
aclrtDestroyStream(s1);
aclrtDestroyEvent(event);
// ......

Stream间任务的同步等待(通过Notify实现)

多Stream之间任务的同步等待可以利用Notify实现,例如,若stream2的任务依赖stream1的任务,想保证stream1中的任务先完成,这时可创建一个Notify,调用aclrtRecordNotify接口将Notify插入到stream1中(通常称为Record Notify任务),调用aclrtWaitAndResetNotify接口在stream2中插入一个等待Notify完成的任务(通常称为Wait Notify任务)。

图2 同步等待流程_多Stream场景

上图中的模型加载与执行的流程请参见模型管理,算子加载与执行的流程请参见单算子调用

调用接口后,需增加异常处理的分支,并记录报错日志、提示日志,此处不一一列举。以下是关键步骤的代码示例,不可以直接拷贝编译运行,仅供参考。

 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
#include "acl/acl.h"
// ......
// 创建一个notify
aclrtNotify notify;
aclrtCreateNotify(&notify, ACL_NOTIFY_FLAG_DEFAULT);


// 创建stream1
aclrtStream s1;
aclrtCreateStream(&s1);

// 创建stream2
aclrtStream s2;
aclrtCreateStream(&s2);

// 在s1末尾添加了一个notify
aclrtRecordNotify(notify, s1);

// 阻塞s2运行,直到指定notify发生,也就是s1执行完成
// s1完成后,唤醒s2,继续执行s2的任务
aclrtWaitAndResetNotify(notify, s2, 0);

aclrtSynchronizeStream(s1);
aclrtSynchronizeStream(s2);

// 显式销毁资源
aclrtDestroyStream(s2);
aclrtDestroyStream(s1);
aclrtDestroyNotify(notify);
// ......

Device的同步等待

调用接口后,需增加异常处理的分支,并记录报错日志、提示日志,此处不一一列举。以下是关键步骤的代码示例,不可以直接拷贝编译运行,仅供参考。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
#include "acl/acl.h"
// ......
// 指定device
aclrtSetDevice(0);

// 创建stream
aclrtStream stream;
aclrtCreateStream(&stream);

// 阻塞应用程序运行,直到正在运算中的Device完成运算
aclrtSynchronizeDevice();

// 资源销毁
aclrtDestroyStream(stream);
aclrtResetDevice(0);