You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
295 lines
9.0 KiB
295 lines
9.0 KiB
/**
|
|
* Copyright 2020-2021 Huawei Technologies Co., Ltd
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#ifndef MINDSPORE_CCSRC_BACKEND_SESSION_KERNEL_BUILD_CLIENT_H_
|
|
#define MINDSPORE_CCSRC_BACKEND_SESSION_KERNEL_BUILD_CLIENT_H_
|
|
|
|
#include <vector>
|
|
#include <string>
|
|
#include <cstring>
|
|
#include <cstdlib>
|
|
#include <memory>
|
|
|
|
#include "common/duplex_pipe.h"
|
|
#include "utils/log_adapter.h"
|
|
#include "utils/ms_context.h"
|
|
|
|
namespace mindspore {
|
|
namespace kernel {
|
|
void ReplaceStr(std::string *dest, const std::string &replace, char new_char);
|
|
|
|
constexpr inline static int kBufferSize = 4096;
|
|
constexpr inline static auto kEnv = "python";
|
|
// The TAG as prefix of real command from remote.
|
|
constexpr inline static auto kTag = "[~]";
|
|
static std::string GetPyExe() {
|
|
// get real python executable path
|
|
auto ms_context = MsContext::GetInstance();
|
|
if (ms_context == nullptr) {
|
|
return kEnv;
|
|
}
|
|
auto env = ms_context->get_param<std::string>(MS_CTX_PYTHON_EXE_PATH);
|
|
if (env.empty()) {
|
|
return kEnv;
|
|
}
|
|
return env;
|
|
}
|
|
|
|
class KernelBuildClient {
|
|
public:
|
|
// Send Finish request to server
|
|
constexpr inline static auto kFinish = "FINISH";
|
|
constexpr inline static auto kAkgStart = "AKG/START";
|
|
constexpr inline static auto kAkgData = "AKG/DATA";
|
|
constexpr inline static auto kAkgWait = "AKG/WAIT";
|
|
// Receive the response from server
|
|
constexpr inline static auto kAck = "ACK";
|
|
constexpr inline static auto kErr = "ERR";
|
|
constexpr inline static auto kTrue = "True";
|
|
constexpr inline static auto kSuccess = "Success";
|
|
|
|
// Revert \n, \r, [space].
|
|
constexpr inline static auto kLF = "[LF]";
|
|
constexpr inline static auto kCR = "[CR]";
|
|
constexpr inline static auto kSP = "[SP]";
|
|
|
|
constexpr inline static unsigned int kTimeOutSeconds = 350;
|
|
|
|
virtual std::string GetEnv() = 0;
|
|
virtual std::string GetScript() = 0;
|
|
|
|
void Open() {
|
|
if (!init_) {
|
|
// Exception's thrown if open failed
|
|
if (dp_->Open({GetEnv(), GetScript()}, true) != -1) {
|
|
dp_->SetFinalizeCallback(std::make_shared<std::function<void()>>([this]() { Close(); }));
|
|
init_ = true;
|
|
}
|
|
}
|
|
}
|
|
void Close() {
|
|
if (init_) {
|
|
dp_->Close();
|
|
init_ = false;
|
|
}
|
|
}
|
|
|
|
// Send a request and fetch its response
|
|
std::string SendRequest(std::string data) {
|
|
Request(data);
|
|
return Response();
|
|
}
|
|
void Request(std::string req) {
|
|
if (!init_) {
|
|
MS_LOG(EXCEPTION) << "Try to send request before Open()";
|
|
}
|
|
MS_LOG(DEBUG) << "\t[" << req << "]";
|
|
*dp_ << req;
|
|
}
|
|
std::string Response() {
|
|
if (!init_) {
|
|
MS_LOG(EXCEPTION) << "Try to get response before Open()";
|
|
}
|
|
std::string res;
|
|
*dp_ >> res;
|
|
// Filter out the interference
|
|
if (res.empty()) {
|
|
MS_LOG(EXCEPTION) << "Response is empty";
|
|
}
|
|
auto start = res.find(kTag);
|
|
if (start == std::string::npos) {
|
|
MS_LOG(EXCEPTION) << "Response seems incorrect, res: " << res;
|
|
}
|
|
auto pos = start + std::strlen(kTag);
|
|
if (pos > res.size()) { // Safe check for codedex
|
|
MS_LOG(EXCEPTION) << "Response seems incorrect, res(" << res.size() << "): {" << res << "}, start: " << start;
|
|
}
|
|
res = res.substr(pos);
|
|
// Revert the line feed and space
|
|
if (res != kSuccess && res != kAck && res != kErr && res != kTrue) {
|
|
ReplaceStr(&res, kLF, '\n');
|
|
ReplaceStr(&res, kSP, ' ');
|
|
}
|
|
MS_LOG(DEBUG) << "\t[" << res << "]";
|
|
return res;
|
|
}
|
|
|
|
// Run AKG building.
|
|
bool AkgStart(int process_num, int wait_time);
|
|
bool AkgSendData(const std::vector<std::string> &jsons);
|
|
bool AkgWait();
|
|
|
|
protected:
|
|
KernelBuildClient() : init_(false), dp_(std::make_shared<DuplexPipe>()) {}
|
|
virtual ~KernelBuildClient() = default;
|
|
|
|
private:
|
|
bool init_;
|
|
std::shared_ptr<DuplexPipe> dp_;
|
|
};
|
|
|
|
static std::string GetScriptFilePath(const std::string cmd_env, const std::string &cmd_script) {
|
|
std::string cmd = cmd_env;
|
|
(void)cmd.append(1, ' ').append(cmd_script);
|
|
FILE *fpipe = popen(cmd.c_str(), "r");
|
|
if (fpipe == nullptr) {
|
|
MS_LOG(EXCEPTION) << "popen failed, errno: " << errno;
|
|
}
|
|
bool start = false;
|
|
std::string result;
|
|
char buf[kBufferSize];
|
|
while (std::fgets(buf, sizeof(buf), fpipe) != nullptr) {
|
|
auto len = std::strlen(buf);
|
|
if (len == 0 || len >= kBufferSize) {
|
|
// Safe check for codedex
|
|
// Should never reach here
|
|
MS_LOG(EXCEPTION) << "fgets() failed, len: " << len << ", errno: " << errno;
|
|
}
|
|
if (std::strncmp(buf, kTag, std::strlen(kTag)) == 0) {
|
|
start = true;
|
|
}
|
|
// Filter with 'kTAG' and '\n'
|
|
if (start) {
|
|
bool line_end = buf[len - 1] == '\n';
|
|
result.append(buf, line_end ? len - 1 : len);
|
|
if (line_end) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
pclose(fpipe);
|
|
const std::string py_suffix = ".py";
|
|
if (result.empty() || result.rfind(py_suffix) != (result.length() - py_suffix.length())) {
|
|
MS_LOG(EXCEPTION) << "py file seems incorrect, result: {" << result << "}";
|
|
}
|
|
if (strlen(kTag) > result.size()) { // Safe check for codedex
|
|
MS_LOG(EXCEPTION) << "result size seems incorrect, result(" << result.size() << "): {" << result << "}";
|
|
}
|
|
result = result.substr(strlen(kTag));
|
|
MS_LOG(DEBUG) << "result: " << result;
|
|
return result;
|
|
}
|
|
|
|
class AscendKernelBuildClient : public KernelBuildClient {
|
|
public:
|
|
// Server configure
|
|
constexpr inline static auto kGetPathScript =
|
|
"-c "
|
|
"\""
|
|
"import pkgutil;"
|
|
"path = pkgutil"
|
|
".get_loader(\\\"mindspore._extends.remote.kernel_build_server_ascend\\\")" // Server module name
|
|
".get_filename();"
|
|
"print('[~]' + path)"
|
|
"\"";
|
|
|
|
// Receive the response from server
|
|
constexpr inline static auto kFailed = "-1";
|
|
|
|
// Send building request to server
|
|
constexpr inline static auto kContinue = "CONTINUE"; // More transactions to be continued
|
|
constexpr inline static auto kTbePre = "TBE/PRE";
|
|
constexpr inline static auto kTbeStart = "TBE/START";
|
|
constexpr inline static auto kTbeWait = "TBE/WAIT";
|
|
constexpr inline static auto kTbeReset = "TBE/RESET";
|
|
constexpr inline static auto kTbeTune = "TBE/TUNE";
|
|
|
|
// Send server info. query to server
|
|
constexpr inline static auto kFormat = "FORMAT";
|
|
constexpr inline static auto kSupport = "SUPPORT";
|
|
|
|
static AscendKernelBuildClient &Instance() {
|
|
static AscendKernelBuildClient instance;
|
|
return instance;
|
|
}
|
|
|
|
std::string GetEnv() override { return GetPyExe(); }
|
|
|
|
std::string GetScript() override {
|
|
auto env = GetPyExe();
|
|
return GetScriptFilePath(env, kGetPathScript);
|
|
}
|
|
|
|
// Before building.
|
|
std::string SelectFormat(const std::string &json);
|
|
bool CheckSupported(const std::string &json);
|
|
|
|
// Run TBE building.
|
|
int TbeStart(const std::string &json, const std::string &mode);
|
|
bool TbeWait(int *task_id, std::string *task_result, std::string *pre_build_result);
|
|
void TbeReset();
|
|
|
|
AscendKernelBuildClient(const AscendKernelBuildClient &) = delete;
|
|
AscendKernelBuildClient &operator=(const AscendKernelBuildClient &) = delete;
|
|
|
|
AscendKernelBuildClient(AscendKernelBuildClient &&) = delete;
|
|
AscendKernelBuildClient &operator=(AscendKernelBuildClient &&) = delete;
|
|
|
|
private:
|
|
bool TbePre(const std::string &mode);
|
|
AscendKernelBuildClient() { Open(); }
|
|
~AscendKernelBuildClient() override { Close(); }
|
|
};
|
|
|
|
class GpuKernelBuildClient : public KernelBuildClient {
|
|
public:
|
|
// Server configure
|
|
constexpr inline static auto kGetPathScript =
|
|
"-c "
|
|
"\""
|
|
"import pkgutil;"
|
|
"path = pkgutil"
|
|
".get_loader(\\\"mindspore._extends.remote.kernel_build_server_gpu\\\")" // Server module name
|
|
".get_filename();"
|
|
"print('[~]' + path)"
|
|
"\"";
|
|
|
|
// Send building request to server
|
|
constexpr inline static auto kAkgPid = "AKG/PID";
|
|
constexpr inline static auto kAkgCompileOp = "AKG/COMPILE"; // Compile a single op
|
|
|
|
static GpuKernelBuildClient &Instance() {
|
|
static GpuKernelBuildClient instance;
|
|
return instance;
|
|
}
|
|
|
|
std::string GetEnv() override { return GetPyExe(); }
|
|
|
|
std::string GetScript() override {
|
|
auto env = GetPyExe();
|
|
return GetScriptFilePath(env, kGetPathScript);
|
|
}
|
|
|
|
// Fetch pid(pid_t) from remote.
|
|
int AkgGetPid();
|
|
// Run AKG building.
|
|
bool AkgCompileSingle(const std::string json);
|
|
|
|
GpuKernelBuildClient(const GpuKernelBuildClient &) = delete;
|
|
GpuKernelBuildClient &operator=(const GpuKernelBuildClient &) = delete;
|
|
|
|
GpuKernelBuildClient(GpuKernelBuildClient &&) = delete;
|
|
GpuKernelBuildClient &operator=(GpuKernelBuildClient &&) = delete;
|
|
|
|
private:
|
|
GpuKernelBuildClient() { Open(); }
|
|
~GpuKernelBuildClient() override { Close(); }
|
|
};
|
|
} // namespace kernel
|
|
} // namespace mindspore
|
|
|
|
#endif // MINDSPORE_CCSRC_BACKEND_SESSION_KERNEL_BUILD_CLIENT_H_
|