日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

AI推理单元

發(fā)布時(shí)間:2023/11/28 生活经验 45 豆豆
生活随笔 收集整理的這篇文章主要介紹了 AI推理单元 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

AI推理單元
推理服務(wù)供了一套面向 MLU(Machine Learning Unit,機(jī)器學(xué)習(xí)單元)設(shè)備的類似服務(wù)器的推理接口(C++11標(biāo)準(zhǔn)),以及模型加載與管理,推理任務(wù)調(diào)度等功能,極大地簡(jiǎn)化了面向MLU平臺(tái)高性能深度學(xué)習(xí)應(yīng)用的開發(fā)和部署工作。
概述
推理服務(wù)在軟件棧中的位置,如下圖所示:

推理服務(wù)共包含以下3個(gè)模塊的用戶接口:
? Model: 模型加載與管理
? Processor: 可自定義的后端處理單元
? InferServer: 執(zhí)行推理任務(wù)
基本概念
本文描述推理服務(wù)中所涉及的具體概念。
InferServer
其整體架構(gòu)如下圖所示

推理服務(wù)架構(gòu)
InferServer 是推理服務(wù)暴露給用戶的功能入口,用戶通過此入口進(jìn)行加載或卸載模型(Model)、創(chuàng)建推理節(jié)點(diǎn)(Session)、請(qǐng)求推理任務(wù)(Request)等操作。 推理任務(wù)劃分為預(yù)處理,推理,后處理三個(gè)環(huán)節(jié),分別交由不同的后端處理單元(Processor)完成。 每個(gè)推理服務(wù)實(shí)例維護(hù)一個(gè)線程池(Scheduler),以處理環(huán)節(jié)(Task)作為最小調(diào)度單元,調(diào)度執(zhí)行在該推理服務(wù)實(shí)例中運(yùn)行的所有推理任務(wù)。
InferServer 使用pimpl指針隔離接口與實(shí)現(xiàn),內(nèi)部保證每個(gè)設(shè)備上僅有一個(gè)pimpl實(shí)例, 同一設(shè)備號(hào)下創(chuàng)建的 InferServer 鏈接同一個(gè)pimpl指針,提供對(duì)應(yīng)功能。
InferServer s_0(0);
InferServer s_1(1);

// another_s_0 和 s_0 共用同一個(gè)任務(wù)調(diào)度器和相同的推理資源
InferServer another_s_0(0);
使用 InferServer 異步接口進(jìn)行推理的步驟如下所示:

  1. 加載離線模型 InferServer::LoadModel() 。
  2. 創(chuàng)建異步推理節(jié)點(diǎn) InferServer::CreateSession() 。
  3. 準(zhǔn)備輸入數(shù)據(jù)。
  4. 提交推理請(qǐng)求 InferServer::Request() ,推理任務(wù)完成后將結(jié)果通過 Observer::Response 發(fā)送給用戶。
  5. 完成所有推理任務(wù)后,釋放推理節(jié)點(diǎn) InferServer::DestroySession() 。
    class MyObserver : public Observer {
    void Response(Status status, PackagePtr output, any user_data) { … }
    };

bool PreprocFunction(ModelIO*, const InferData&, const ModelInfo&) { … }

// prepare resources
InferServer server(0);

SessionDesc desc;
desc.name = “sample infer”;
desc.model = InferServer::LoadModel(model_path, func_name);
// create processors
desc.preproc = PreprocessorHost::Create();
desc.postproc = Postprocessor::Create();
desc.preproc->SetParams(“process_function”, PreprocFunction);

Session_t session = server.CreateSession(desc, std::make_shared());

// run inference
// create an input package with tag “stream_0”, containing two piece of InferData
auto input = Package::Create(2, “stream_0”);
input->data[0].Setcv::Mat(image_1);
input->data[1].Setcv::Mat(image_2);

server.Request(session, input, nullptr);
// result will be passed to MyObserver::Response after finishing process

// wait until the “stream_0” tagged inference task done
server.WaitTaskDone(session, “stream_0”);

// release resources
server.DestroySession(session);
ModelInfo
ModelInfo 提供了易用的用戶側(cè)模型管理和信息讀取接口,各種模型實(shí)現(xiàn)的基類。 由 InferServer::LoadModel() 加載模型,得到模型基類的智能指針。當(dāng)所有實(shí)例生命周期結(jié)束后,模型自動(dòng)卸載。 用戶可隨時(shí)獲取模型的各種信息,包含輸入輸出個(gè)數(shù)、輸入輸出數(shù)據(jù)形狀以及batch_size等。
Session
Session 是推理任務(wù)節(jié)點(diǎn)的抽象,接收用戶的推理請(qǐng)求并完成響應(yīng)。一個(gè)Session為一個(gè)處理節(jié)點(diǎn),內(nèi)部的后端處理單元的順序結(jié)構(gòu)是固定的,處理同一類請(qǐng)求。
使用 InferServer::CreateSession 創(chuàng)建異步Session,異步Session只能使用異步 Request 接口,處理完畢后通過 Observer::Response 發(fā)送響應(yīng)給用戶; 使用 InferServer::CreateSyncSession 創(chuàng)建同步Session,同步Session只能使用同步 RequestSync 接口,響應(yīng)作為 RequestSync 的輸出參數(shù)返回。
InferServer s(0);
SessionDesc desc;
/*

  • set desc params

  • */
    Session_t async_session = s.CreateSession(desc, std::make_shared());
    Session_t sync_session = s.CreateSyncSession(desc);

s.Request(async_session, input, user_data);
s.RequestSync(sync_session, input, &status, output);
Session根據(jù)傳入的參數(shù)準(zhǔn)備 SessionDesc::engine_num 份推理資源,使每份推理資源可以獨(dú)立執(zhí)行任務(wù),達(dá)成并行推理。
注解
模型鍵值拼接預(yù)處理和后處理單元類型名稱(modelkey_preproc_postproc)作為Session的鍵值,鍵值相同的Session共用同一簇推理資源。
Processor
后端處理單元,負(fù)責(zé)處理推理任務(wù)中的一個(gè)環(huán)節(jié),由多個(gè) Processor 鏈接起來構(gòu)成整個(gè)推理任務(wù)處理流程。
BaseObject 基類為 Processor 提供設(shè)置任意參數(shù)的功能。
MyProcessor p;
p.SetParams(“some int param”, 1,
“some string param”, “some string”);
int a = p.GetParam(“some int param”);
const char* b = p.GetParam<const char*>(“some string”);
InferData
InferData 表示一份推理數(shù)據(jù),基于C++11編譯器實(shí)現(xiàn)的 any 類使任意類型的推理數(shù)據(jù)都可以在 InferData 中設(shè)置。
InferData data;
cv::Mat opencv_image;
// 填充數(shù)據(jù)到InferData
data.Set(opencv_image);
// 獲取一份數(shù)據(jù)的復(fù)制
auto image = data.Getcv::Mat();
// 獲取一份數(shù)據(jù)的引用
auto& image_ref = data.GetLrefcv::Mat();
try {
// 類型不匹配,拋出異常bad_any_cast!
auto non_sense = data.Get();
} catch (bad_any_cast&) {
std::cout << “Data stored in any cannot convert to given type!”;
}

video::VideoFrame vframe;
// 重新設(shè)置data后image_ref非法化
data.Set(vframe);
// cv::imwrite(“foo.jpg”, image_ref); // may cause segment fault
auto frame = data.Getvideo::VideoFrame();
auto& frame_ref = data.GetLrefvideo::VideoFrame();
Package
Package 是一組推理數(shù)據(jù)的集合,既是Request的輸入,也是Response的輸出。用戶通過Package可以一次請(qǐng)求多份數(shù)據(jù)進(jìn)行處理。
使能 CNIS_RECORD_PERF 編譯選項(xiàng)時(shí), 輸出中 Package::perf 包含每一個(gè)處理環(huán)節(jié)的性能數(shù)據(jù),未使能時(shí)為空表。
Observer
進(jìn)行異步請(qǐng)求需要在創(chuàng)建Session時(shí),設(shè)置Observer實(shí)例。Session完成推理任務(wù)后,以通知Observer的方式完成Response。
class MyObserver : public Observer {
void Response(Status status, PackagePtr output, any user_data) {
std::cout << “Get one response\n”;
}
};

InferServer s(0);
SessionDesc desc;
Session_t async_session = s.CreateSession(desc, std::make_shared());
功能
本文詳細(xì)介紹推理服務(wù)的功能。
模型加載與管理
推理服務(wù)提供模型加載和管理功能,并在全局保有唯一一份模型緩存。
使用 InferServer::LoadModel(const std::string& uri, const std::string& func_name = “subnet0”) 從本地路徑加載模型, 若使能 CNIS_WITH_CURL 編譯選項(xiàng),則可以從遠(yuǎn)端下載模型, 并加載至模型存儲(chǔ)路徑(由 InferServer::SetModelDir 設(shè)置, 默認(rèn)值為當(dāng)前目錄)。 當(dāng)檢測(cè)到模型存儲(chǔ)路徑中已存在同名模型,則跳過下載,直接加載本地模型(請(qǐng)注意不要使用相同的模型名,可能會(huì)導(dǎo)致使用錯(cuò)誤的模型)。 使用 InferServer::LoadModel(void* mem_ptr, const std::string& func_name = “subnet0”) 從內(nèi)存中加載模型,適用于模型加密的場(chǎng)景, 由用戶對(duì)存儲(chǔ)的模型解密后交由推理服務(wù)進(jìn)行加載。
將模型路徑和模型函數(shù)名進(jìn)行拼接作為鍵值,對(duì)模型進(jìn)行區(qū)分(從內(nèi)存加載的模型路徑是內(nèi)存地址字符串)。 若加載模型時(shí)發(fā)現(xiàn)緩存中已存在該模型,則直接返回緩存模型。 模型緩存存在上限,超出上限自動(dòng)卸載未在使用的模型。上限默認(rèn)值是10,可通過環(huán)境變量 CNIS_MODEL_CACHE_LIMIT 更改默認(rèn)值。 支持運(yùn)行時(shí)清除模型緩存,從緩存中清除不會(huì)直接卸載模型,僅在無其他模型的智能指針實(shí)例時(shí)才會(huì)卸載模型(確保模型已經(jīng)沒有在使用,避免功能性錯(cuò)誤)。
ModelPtr local_model = InferServer::LoadModel("…/…/resnet.cambricon", “subnet0”);
// use function name “subnet0” as default
ModelPtr local_model = InferServer::LoadModel("…/…/resnet.cambricon");
ModelPtr net_model = InferServer::LoadModel(“http://some-web.com/resnet.cambricon”);

void model_mem, decoded_model_mem;
size_t len = ReadFromFile(model_mem, …);
DecodeModel(decoded_model_mem, model_mem, len, …);
ModelPtr mem_model = InferServer::LoadModel(decoded_model_mem);
推理任務(wù)調(diào)度
推理服務(wù)對(duì)所有請(qǐng)求的推理任務(wù)進(jìn)行調(diào)度,以在保證通用性的前提下盡量達(dá)到最優(yōu)性能。 推理服務(wù)使用三種共同作用的調(diào)度方式:批處理、優(yōu)先級(jí)和并行處理。
批處理(Batch)
推理服務(wù)提供兩種批處理模式,Dynamic模式( BatchStrategy::DYNAMIC )和Static模式( BatchStrategy::STATIC ), 在創(chuàng)建Session時(shí)通過 SessionDesc::strategy 指定。
? Dynamic模式會(huì)跨Request拼湊批數(shù)據(jù),盡可能使用性能最優(yōu)的批大小進(jìn)行處理,達(dá)到較為理想的吞吐。 但由于跨Request拼湊數(shù)據(jù)會(huì)存在等待數(shù)據(jù)集齊的時(shí)間,單次Request的時(shí)延較高。達(dá)到設(shè)置的timeout時(shí)間后,即使未集齊批也會(huì)進(jìn)行處理,以避免時(shí)延過高。
? Static模式以用戶每次輸入的Request數(shù)據(jù)為一批,不跨Request拼湊數(shù)據(jù),可以達(dá)到較為理想的單次Request時(shí)延。 但相較于Dynamic模式更難達(dá)到性能較優(yōu)的批大小,總吞吐量較Dynamic模式略低。
注解
目前底層尚未支持帶狀態(tài)的離線模型,待后端支持后,會(huì)增量支持Sequence模式的批處理策略。
優(yōu)先級(jí)(Priority)
每個(gè)設(shè)備上的所有推理任務(wù)共用同一個(gè)調(diào)度器。 用戶可以在創(chuàng)建Session時(shí)通過 SessionDesc::priority 設(shè)置優(yōu)先級(jí),高優(yōu)先級(jí)的Session中的任務(wù)將會(huì)優(yōu)先被處理。 優(yōu)先級(jí)限制為0~9的整數(shù),數(shù)值越大優(yōu)先級(jí)越高,低于0的按0處理,高于9的按9處理。
并行處理(Parallel)
為達(dá)到最大性能,通常需要在一個(gè)設(shè)備上并行執(zhí)行多組推理任務(wù)。 若某個(gè)Session代表的一類推理任務(wù)負(fù)載較重,可以通過設(shè)置 SessionDesc::engine_num 增大該類推理任務(wù)的并行度, 使該Session共占用 engine_num * model_core_number 個(gè)計(jì)算核,和對(duì)應(yīng)份推理資源(內(nèi)存,模型指令等)。 超出上限后,繼續(xù)增加engine_num,可能出現(xiàn)由于資源競(jìng)爭(zhēng)導(dǎo)致的總吞吐下降的情況。
后端處理單元(Processor)
推理服務(wù)內(nèi)置三種后端處理單元。
預(yù)處理
預(yù)處理單元完成輸入數(shù)據(jù)預(yù)處理的功能,推理服務(wù)內(nèi)置了通用的預(yù)處理單元PreprocessorHost(在CPU側(cè)完成運(yùn)算)。 用戶提供單份數(shù)據(jù)預(yù)處理的方法 bool(ModelIO
, const InferData&, const ModelInfo&) , 通過 BaseObject::SetParams(“process_function”, func_ptr) 設(shè)置給 PreprocessorHost , 內(nèi)置預(yù)處理單元內(nèi)部實(shí)現(xiàn)并發(fā)對(duì)批數(shù)據(jù)進(jìn)行任務(wù)處理,完成預(yù)處理后轉(zhuǎn)換數(shù)據(jù)擺放 (從用戶設(shè)置的 SessionDesc::host_input_layout 轉(zhuǎn)換至模型接受的layout),拷貝入MLU,轉(zhuǎn)給推理單元處理。 由于預(yù)處理函數(shù)由用戶設(shè)置,預(yù)處理函數(shù)的輸入是可保有任意類型數(shù)據(jù)的 InferData , 輸出是固定類型的 ModelIO,故支持輸入任意類型數(shù)據(jù)做推理。
注解
由用戶提供的數(shù)據(jù)預(yù)處理方法僅處理單份數(shù)據(jù),假如一個(gè)預(yù)處理過程(執(zhí)行一次Process方法)的數(shù)據(jù)包中存在多份數(shù)據(jù),多份數(shù)據(jù)將會(huì)被拆分,每份數(shù)據(jù)分別調(diào)用預(yù)處理方法并發(fā)執(zhí)行預(yù)處理任務(wù)。
InferServer s(0);
SessionDesc desc;
desc.preproc = std::make_shared();
desc.preproc->SetParams(“process_function”, some_func);
/

  • set desc params

  • /
    Session_t sync_session = s.CreateSyncSession(desc);
    預(yù)處理參數(shù)表
    參數(shù)名稱 默認(rèn)值 范圍 描述
    parallel 2 [1, 8] 處理并行度
    process_function nullptr N/A 用戶定義的預(yù)處理方法
    推理
    推理單元完成推理任務(wù)(暫不支持用戶設(shè)置推理單元,所有Session默認(rèn)使用內(nèi)置的推理單元)。 每個(gè)推理單元實(shí)例從模型獲取包含指令數(shù)據(jù)的Context,多份Context由 cnrtForkRuntimeContext 生成,以避免指令的多份拷貝。 推理單元接受固定類型的輸入,輸出固定類型的推理結(jié)果( ModelIO ),輸入輸出數(shù)據(jù)均在MLU內(nèi)存上。 推理完成后,將推理結(jié)果數(shù)據(jù)轉(zhuǎn)至后處理單元解析。
    后處理
    后處理單元完成推理結(jié)果的拷貝和解析,推理服務(wù)內(nèi)置了通用的后處理單元Postprocessor(在CPU側(cè)完成運(yùn)算)。 后處理單元首先將推理結(jié)果從MLU設(shè)備拷貝回CPU,并轉(zhuǎn)換數(shù)據(jù)擺放格式(從模型輸出的layout轉(zhuǎn)換至用戶設(shè)置的 SessionDesc::host_output_layout )。 用戶提供單份數(shù)據(jù)后處理的方法 bool(InferData
    , const ModelIO&, const ModelInfo&) , 通過 BaseObject::SetParams(“process_function”, func_ptr) 設(shè)置給 Postprocessor , 內(nèi)置后處理單元內(nèi)部實(shí)現(xiàn)并發(fā),調(diào)用用戶設(shè)置的方法對(duì)模型輸出的批數(shù)據(jù)進(jìn)行解析任務(wù)。
    注解
    由用戶提供的數(shù)據(jù)后處理方法僅處理單份數(shù)據(jù),假如一個(gè)后處理過程(執(zhí)行一次Process方法)的數(shù)據(jù)包中存在多份數(shù)據(jù),多份數(shù)據(jù)將會(huì)被拆分,每份數(shù)據(jù)分別調(diào)用后處理方法并發(fā)執(zhí)行后處理任務(wù)。
    InferServer s(0);
    SessionDesc desc;
    desc.postproc = std::make_shared();
    desc.postproc->SetParams(“process_function”, some_func);
    /*
  • set desc params

  • /
    Session_t sync_session = s.CreateSyncSession(desc);
    若用戶未設(shè)置后處理方法,則僅執(zhí)行拷貝和轉(zhuǎn)換layout操作,后處理單元輸出CPU上的 ModelIO 數(shù)據(jù)。 此種情況下,用戶無需在 SessionDesc 中設(shè)置postproc,保持默認(rèn)值nullptr將自動(dòng)創(chuàng)建一個(gè)僅執(zhí)行拷貝操作的Postprocessor。
    后處理參數(shù)表
    參數(shù)名稱 默認(rèn)值 范圍 描述
    parallel 2 [1, 8] 處理并行度
    process_function nullptr N/A 用戶定義的后處理方法
    擴(kuò)展接口(contrib)
    推理服務(wù)提供對(duì)圖像推理任務(wù)的特化接口,簡(jiǎn)化圖像推理過程, 其中包括 VideoFrame 數(shù)據(jù)類型,針對(duì)該數(shù)據(jù)類型的MLU預(yù)處理單元 PreprocessorMLU, OpenCV特化數(shù)據(jù)類型 OpencvFrame ,針對(duì)該數(shù)據(jù)類型的CPU預(yù)處理仿函數(shù) DefaultOpencvPreproc , 請(qǐng)求推理任務(wù)簡(jiǎn)化接口的 VideoInferServer ,繼承自 InferServer 。
    // 一級(jí)推理接口
    bool Request(Session_t session, const VideoFrame& vframe,
    const std::string& tag, any user_data, int timeout = -1) noexcept;
    bool RequestSync(Session_t session, const VideoFrame& vframe, const std::string& tag,
    Status
    status, PackagePtr output, int timeout = -1) noexcept;

// 二級(jí)分析接口
bool Request(Session_t session, const VideoFrame& vframe, const std::vector& objs,
const std::string& tag, any user_data, int timeout = -1) noexcept;
bool RequestSync(Session_t session, const VideoFrame& vframe,
const std::vector& objs, const std::string& tag,
Status* status, PackagePtr output, int timeout = -1) noexcept;
InferServer s(0);
SessionDesc desc;
desc.preproc = std::make_shared();
// 使用OpenCV實(shí)現(xiàn)的預(yù)處理函數(shù)
desc.preproc->SetParams(“process_function”, video::DefaultOpencvPreproc::GetFunction());

Session_t sync_session = s.CreateSyncSession(desc);
InferServer s(0);
SessionDesc desc;
// 使用MLU預(yù)處理單元
desc.preproc = std::make_sharedvideo::PreprocessorMLU();
desc.preproc->SetParams(“src_format”, video::PixelFmt::NV21,
“dst_format”, video::PixelFmt::RGBA,
“preprocess_type”, video::PreprocessType::RESIZE_CONVERT);

Session_t sync_session = s.CreateSyncSession(desc);

PreprocessorMLU 單元內(nèi)置了BANG語言實(shí)現(xiàn)的 ResizeConvert 算子,和硬件scaler(僅MLU220支持),提供MLU上的預(yù)處理功能,支持YUV轉(zhuǎn)至四通道BGR家族,同時(shí)圖像縮放至指定大小。
擴(kuò)展預(yù)處理參數(shù)表

參數(shù) core_number 和 keep_aspect_ratio 僅對(duì) RESIZE_CONVERT 生效。

總結(jié)

以上是生活随笔為你收集整理的AI推理单元的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。