Skip to content

Commit aab1f9e

Browse files
author
Leo Zhao
authored
[INTEL_HPU] re-enable async runner and do enhancement (#1934)
1 parent 9bdac9a commit aab1f9e

3 files changed

Lines changed: 310 additions & 179 deletions

File tree

backends/intel_hpu/kernels/hpu_operator.cc

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@ FLAGS_DEFINE_bool(intel_hpu_sync_execute, false, "set sync execute mode");
3131
FLAGS_DEFINE_bool(intel_hpu_reciperunner_debug,
3232
false,
3333
"reciperunner debug log");
34+
FLAGS_DEFINE_bool(intel_hpu_async_runner_multithread,
35+
false,
36+
"enable async runner multi-threading support");
3437

3538
typedef std::pair<synSectionHandle, bool> sectionWithFirstIndication;
3639
static std::unordered_map<std::string, sectionWithFirstIndication> sectionMap;
@@ -142,6 +145,47 @@ void RecipeRunner::prepareTensorInfo(synRecipeHandle recipe,
142145
}
143146

144147
#ifdef ENABLE_ASYNC_RUN
148+
void GlobalWorkStreamExecutor::add_task(const synStreamHandle stream,
149+
std::function<void()> task) {
150+
std::shared_ptr<WorkerThread> worker;
151+
152+
synStreamHandle workstream = nullptr;
153+
if (FLAGS_intel_hpu_async_runner_multithread) workstream = stream;
154+
155+
{
156+
std::lock_guard<std::mutex> lock(workers_mutex_);
157+
if (workers_.find(workstream) == workers_.end()) {
158+
worker = std::make_shared<WorkerThread>();
159+
worker->thread = std::thread([this, workstream, worker]() {
160+
while (true) {
161+
std::function<void()> task;
162+
{
163+
std::unique_lock<std::mutex> lock(worker->mutex);
164+
worker->condition.wait(lock, [worker] {
165+
return !worker->tasks.empty() || worker->stop;
166+
});
167+
168+
if (worker->stop && worker->tasks.empty()) break;
169+
170+
task = std::move(worker->tasks.front());
171+
worker->tasks.pop();
172+
}
173+
task();
174+
}
175+
});
176+
workers_[workstream] = worker;
177+
} else {
178+
worker = workers_[workstream];
179+
}
180+
}
181+
182+
{
183+
std::lock_guard<std::mutex> lock(worker->mutex);
184+
worker->tasks.emplace(std::move(task));
185+
}
186+
worker->condition.notify_one();
187+
}
188+
145189
void RecipeRunner::ExecuteRecipe(C_Stream stream,
146190
const std::map<std::string, uint64_t>& tensors,
147191
synRecipeHandle recipeHandle_) {

backends/intel_hpu/kernels/hpu_operator.h

Lines changed: 32 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
#include "paddle/phi/common/type_traits.h"
3434
#include "paddle/phi/extension.h"
3535

36-
// #define ENABLE_ASYNC_RUN
36+
#define ENABLE_ASYNC_RUN
3737

3838
class HpuOperator {
3939
public:
@@ -88,78 +88,64 @@ class GlobalWorkStreamExecutor {
8888
}
8989

9090
template <typename R>
91-
std::future<R> async(std::function<R()> func) {
91+
std::future<R> async(synStreamHandle stream, std::function<R()> func) {
9292
auto task = std::make_shared<std::packaged_task<R()>>(std::move(func));
9393
std::future<R> res = task->get_future();
94-
add_task([task]() { (*task)(); });
94+
add_task(stream, [task]() { (*task)(); });
9595
return res;
9696
}
9797

9898
template <typename F>
99-
auto async(F&& func) -> std::future<decltype(func())> {
99+
auto async(synStreamHandle stream, F&& func)
100+
-> std::future<decltype(func())> {
100101
using R = decltype(func());
101102
auto task =
102103
std::make_shared<std::packaged_task<R()>>(std::forward<F>(func));
103104
std::future<R> res = task->get_future();
104-
add_task([task]() { (*task)(); });
105+
add_task(stream, [task]() { (*task)(); });
105106
return res;
106107
}
107108

108109
template <typename R>
109-
R sync(std::function<R()> func) {
110-
return async(std::move(func)).get();
110+
R sync(synStreamHandle stream, std::function<R()> func) {
111+
return async(stream, std::move(func)).get();
111112
}
112113

113114
template <typename F>
114-
auto sync(F&& func) -> decltype(func()) {
115-
return async(std::forward<F>(func)).get();
115+
auto sync(synStreamHandle stream, F&& func) -> decltype(func()) {
116+
return async(stream, std::forward<F>(func)).get();
116117
}
117118

118119
private:
119-
GlobalWorkStreamExecutor() {
120-
worker_ = std::thread([this]() {
121-
while (true) {
122-
std::function<void()> task;
123-
{
124-
std::unique_lock<std::mutex> lock(queue_mutex_);
125-
condition_.wait(lock, [this] { return !tasks_.empty() || stop_; });
126-
127-
if (stop_ && tasks_.empty()) break;
128-
129-
task = std::move(tasks_.front());
130-
tasks_.pop();
131-
}
132-
task(); // 执行任务
133-
}
134-
});
135-
}
136-
120+
struct WorkerThread {
121+
std::thread thread;
122+
std::queue<std::function<void()>> tasks;
123+
std::mutex mutex;
124+
std::condition_variable condition;
125+
bool stop = false;
126+
};
127+
128+
GlobalWorkStreamExecutor() = default;
137129
~GlobalWorkStreamExecutor() {
138-
{
139-
std::lock_guard<std::mutex> lock(queue_mutex_);
140-
stop_ = true;
130+
for (auto& [stream, worker] : workers_) {
131+
{
132+
std::lock_guard<std::mutex> lock(worker->mutex);
133+
worker->stop = true;
134+
}
135+
worker->condition.notify_all();
136+
if (worker->thread.joinable()) {
137+
worker->thread.join();
138+
}
141139
}
142-
condition_.notify_all();
143-
if (worker_.joinable()) worker_.join();
144140
}
145141

146-
void add_task(std::function<void()> task) {
147-
{
148-
std::lock_guard<std::mutex> lock(queue_mutex_);
149-
tasks_.emplace(std::move(task));
150-
}
151-
condition_.notify_one();
152-
}
142+
void add_task(const synStreamHandle stream, std::function<void()> task);
153143

154-
// 删除拷贝构造和赋值
155144
GlobalWorkStreamExecutor(const GlobalWorkStreamExecutor&) = delete;
156145
GlobalWorkStreamExecutor& operator=(const GlobalWorkStreamExecutor&) = delete;
157146

158-
std::thread worker_;
159-
std::queue<std::function<void()>> tasks_;
160-
std::mutex queue_mutex_;
161-
std::condition_variable condition_;
162-
bool stop_ = false;
147+
std::unordered_map<synStreamHandle, std::shared_ptr<WorkerThread>> workers_;
148+
std::mutex workers_mutex_;
163149
};
164150
#endif
165151

@@ -175,6 +161,7 @@ class RecipeRunner {
175161
void Run(C_Stream stream, std::map<std::string, uint64_t> tensors) {
176162
synRecipeHandle recipehandle = this->recipeHandle_;
177163
auto future = GlobalWorkStreamExecutor::instance().async(
164+
reinterpret_cast<synStreamHandle>(stream),
178165
[this, stream, tensors, recipehandle] {
179166
ExecuteRecipe(stream, tensors, recipehandle);
180167
});

0 commit comments

Comments
 (0)