日韩精品一区二区三区在线视频放-无码中文字幕V?一区二区-成年片免费观看视频-国内少妇人妻丰满av-国产精品中文字幕免费观看-亚洲成人久久一区二区三区-国内少妇偷人精品视频无缓冲-一区二区国产精品日本一区二区三区在线网

ARTICLE DETAIL

資訊詳情

深耕商務(wù)建站與企業(yè)官網(wǎng)運(yùn)營(yíng)的一線實(shí)戰(zhàn)洞察。

高通QNN SDK實(shí)戰(zhàn):從模型轉(zhuǎn)換到C++推理全流程指南

高通QNN SDK實(shí)戰(zhàn):從模型轉(zhuǎn)換到C++推理全流程指南 在驍龍平臺(tái)做AI推理最忌諱的是把模型拿來(lái)直接在CPU上跑一遍就宣布完事硬件加速能力一點(diǎn)都沒(méi)用上。Qualcomm QNN SDK本來(lái)就提供了一整套從模型轉(zhuǎn)換、量化到C/C運(yùn)行時(shí)調(diào)用的工具鏈大多數(shù)人卡住的地方其實(shí)就兩個(gè)模型不知道怎么轉(zhuǎn)成QNN格式C代碼不知道從哪個(gè)接口下手。這篇文章把這條路完整走一遍從環(huán)境準(zhǔn)備到代碼解析最后再到排坑你可以把它當(dāng)成一份能照著跑的作業(yè)。1. 項(xiàng)目全景與方案設(shè)計(jì)先從QNN的整體架構(gòu)說(shuō)起動(dòng)手寫(xiě)代碼之前先把QNN這套東西的地圖畫(huà)出來(lái)。很多人被QNN勸退不是因?yàn)榇a難寫(xiě)而是因?yàn)楦拍畈皇臁R活^扎進(jìn)去看到一堆Handle、Descriptor、Profile直接就懵了。其實(shí)QNN的架構(gòu)分得非常清晰理解了那幾條主線后面所有代碼都只是在跟這幾條主線打交道。1.1 QNN SDK到底是什么為什么選它QNN SDK是高通提供的神經(jīng)網(wǎng)絡(luò)推理SDK跑在驍龍平臺(tái)上時(shí)它能把模型調(diào)度到Hexagon DSP或者HTPHexagon Tensor Processor上執(zhí)行。HTP是高通專(zhuān)門(mén)為AI推理設(shè)計(jì)的硬件加速單元比CPU省電吞吐能力高出好幾個(gè)量級(jí)。常見(jiàn)的分類(lèi)、檢測(cè)、分割模型經(jīng)過(guò)合理量化之后在HTP上都能跑得飛快。從架構(gòu)上看QNN分兩層一層是Host側(cè)也就是你的C應(yīng)用跑在CPU上的部分另一層是Device側(cè)也就是跑在DSP/HTP上的部分。Host側(cè)通過(guò)QNN提供的Backend接口跟Device側(cè)打交道。像libQnnHtp.so就是HTP的Backend實(shí)現(xiàn)庫(kù)你的程序通過(guò)dlopen或者運(yùn)行時(shí)鏈接的方式加載它然后調(diào)用統(tǒng)一的QNN接口剩下的調(diào)度工作全部交給SDK完成。很多人會(huì)問(wèn)既然有TFLite、ONNX Runtime這些跨平臺(tái)框架為什么還要折騰QNN原因很簡(jiǎn)單模型要跑得夠快夠省電就必須直接調(diào)用硬件能力。跨平臺(tái)框架為了兼容性往往走的是通用優(yōu)化路徑對(duì)特定硬件的利用程度有限。QNN能直接操作DSP/HTP上的張量緩沖區(qū)和執(zhí)行流水線量化模型跑起來(lái)經(jīng)常比CPU快一個(gè)數(shù)量級(jí)。如果你做的是端側(cè)攝像頭、語(yǔ)音助手、手勢(shì)識(shí)別這類(lèi)對(duì)延遲和功耗極度敏感的場(chǎng)景QNN幾乎繞不開(kāi)。1.2 完整鏈路拆解從模型轉(zhuǎn)換到C推理一個(gè)模型要跑在QNN上鏈路其實(shí)可以拆成五段準(zhǔn)備模型文件PyTorch導(dǎo)出ONNX或者直接拿TensorFlow/TFLite模型。使用qnn-onnx-converter把ONNX轉(zhuǎn)成QNN的圖描述文件.serialized。使用qnn-context-binary-generator把圖描述文件和HTP Backend綁定生成一個(gè)Context Binary。編寫(xiě)C程序加載Backend庫(kù)和Context Binary。創(chuàng)建輸入輸出張量執(zhí)行推理讀取結(jié)果。很多人會(huì)直接跳到第4步結(jié)果發(fā)現(xiàn)怎么都跑不通原因就是沒(méi)有理解Context Binary的作用。Context Binary可以理解為一份提前構(gòu)建好的執(zhí)行計(jì)劃它把模型的算子調(diào)度、內(nèi)存分配、常量數(shù)據(jù)全部打包在一起。運(yùn)行時(shí)只需要把這個(gè)二進(jìn)制文件加載進(jìn)去SDK就能直接在HTP上創(chuàng)建對(duì)應(yīng)的執(zhí)行上下文不用再一條一條去解析算子、做圖優(yōu)化。這一點(diǎn)非常重要。如果你在運(yùn)行時(shí)才去構(gòu)建圖每次啟動(dòng)都要重新做一遍算子的挑選和內(nèi)存規(guī)劃冷啟動(dòng)時(shí)間可能多出幾百毫秒甚至幾秒。而Context Binary方案把重活全部放在離線階段完成運(yùn)行時(shí)就是純加載速度極快。這也是為什么高通官方在端側(cè)部署時(shí)推薦的生產(chǎn)路徑就是Context Binary。1.3 方案取舍用Graph API還是直接用Context BinaryQNN其實(shí)提供了兩條運(yùn)行路徑一條是直接用Graph API在運(yùn)行時(shí)裝圖另一條就是上面說(shuō)的加載Context Binary。從我實(shí)際用下來(lái)的感受來(lái)看除非你在做的是需要?jiǎng)討B(tài)修改網(wǎng)絡(luò)結(jié)構(gòu)的實(shí)驗(yàn)場(chǎng)景否則生產(chǎn)環(huán)境一定要走Context Binary。Graph API在運(yùn)行時(shí)構(gòu)建圖的好處是比較靈活可以在代碼里動(dòng)態(tài)指定張量維度、插入算子適合原型驗(yàn)證。但壞處也很明顯每次初始化都要完成完整的圖構(gòu)建流程而且需要在目標(biāo)設(shè)備上具備完整的算子庫(kù)和轉(zhuǎn)換工具鏈。這會(huì)讓程序的啟動(dòng)時(shí)間變長(zhǎng)還容易因?yàn)檫\(yùn)行環(huán)境和轉(zhuǎn)換環(huán)境不一致導(dǎo)致各種奇奇怪怪的算子兼容問(wèn)題。Context Binary則是把模型在開(kāi)發(fā)機(jī)上轉(zhuǎn)換完畢把校驗(yàn)也做掉之后再把二進(jìn)制文件放進(jìn)設(shè)備里。運(yùn)行時(shí)的代碼路徑極大簡(jiǎn)化就變成幾行固定的調(diào)用標(biāo)準(zhǔn)流程。就算產(chǎn)品發(fā)布了多個(gè)模型版本只要替換二進(jìn)制文件就行C代碼基本不用動(dòng)。我建議做產(chǎn)品落地的朋友直接采用這條路徑下面所有的代碼也都是按這個(gè)方案來(lái)寫(xiě)的。2. 環(huán)境準(zhǔn)備與模型轉(zhuǎn)換這一步值80%的調(diào)試時(shí)間說(shuō)實(shí)話QNN項(xiàng)目里真正耗時(shí)間的往往不是寫(xiě)代碼而是環(huán)境搭建和模型轉(zhuǎn)換。很多人編譯報(bào)錯(cuò)、運(yùn)行崩潰最后發(fā)現(xiàn)都是SDK版本不匹配、交叉編譯工具鏈不對(duì)、模型轉(zhuǎn)換時(shí)埋了雷。環(huán)境準(zhǔn)備這一章認(rèn)真看能幫你省下大量排坑時(shí)間。2.1 SDK版本與交叉編譯工具鏈準(zhǔn)備我用的是高通發(fā)布的QNN SDK 2.x版本不同版本接口細(xì)節(jié)略有差異但整體思路是一致的。拿到SDK壓縮包之后解壓到某個(gè)目錄然后設(shè)置環(huán)境變量export QNN_SDK_ROOT/path/to/qnn-sdk export LD_LIBRARY_PATH$QNN_SDK_ROOT/lib/aarch64-unknown-linux-gnu:$LD_LIBRARY_PATH export PATH$QNN_SDK_ROOT/bin/aarch64-unknown-linux-gnu:$PATH注意SDK里的lib目錄下通常會(huì)區(qū)分x86_64-linux-clang和aarch64-unknown-linux-gnu等多個(gè)平臺(tái)目錄。你這臺(tái)開(kāi)發(fā)機(jī)用的轉(zhuǎn)換工具比如qnn-onnx-converter一般是x86的Python腳本但運(yùn)行時(shí)加載的libQnnHtp.so必須選目標(biāo)設(shè)備對(duì)應(yīng)的架構(gòu)版本。如果程序跑在ARM64的Linux板子上就一定要把a(bǔ)arch64-unknown-linux-gnu目錄下的庫(kù)優(yōu)先加進(jìn)LD_LIBRARY_PATH而不是用x86的庫(kù)去跑否則直接報(bào)無(wú)法加載動(dòng)態(tài)庫(kù)。交叉編譯時(shí)還是要用aarch64的GCC工具鏈。我這邊用的是aarch64-linux-gnu-g版本建議在10以上太老的編譯器對(duì)C17支持不友好后面代碼里的智能指針、lambda寫(xiě)起來(lái)會(huì)比較別扭。提前在板子上裝好對(duì)應(yīng)的依賴庫(kù)比如libstdc、libc這種基礎(chǔ)運(yùn)行庫(kù)避免把編譯產(chǎn)物拷過(guò)去之后才發(fā)現(xiàn)缺符號(hào)。如果你跑的是Windows on Snapdragon平臺(tái)那工具鏈又不太一樣要用MSVC或者Clang配合高通提供的Windows庫(kù)。今天這篇主要講Linux環(huán)境但代碼邏輯在Windows上一樣能套用關(guān)鍵路徑都是那些接口函數(shù)。2.2 從PyTorch導(dǎo)出ONNX的操作要點(diǎn)我們?cè)赒NN里最常見(jiàn)的第一步是把PyTorch模型導(dǎo)出成ONNX。導(dǎo)出命令很簡(jiǎn)單import torch model torch.load(model.pth, map_locationcpu) model.eval() dummy_input torch.randn(1, 3, 224, 224) torch.onnx.export( model, dummy_input, model.onnx, opset_version13, input_names[input_0], output_names[output_0], dynamic_axes{input_0: {0: batch}, output_0: {0: batch}} )這里有幾個(gè)細(xì)節(jié)非常關(guān)鍵。第一opset_version盡量選13或更高QNN轉(zhuǎn)換器對(duì)高版本opset的支持更完善低版本有些算子表達(dá)過(guò)于簡(jiǎn)陋轉(zhuǎn)換器反而容易踩坑。第二dynamic_axes一定要設(shè)置成動(dòng)態(tài)batch因?yàn)镼NN轉(zhuǎn)換器在解析ONNX時(shí)會(huì)對(duì)張量維度做靜態(tài)推理如果你把batch固定為1后續(xù)想換不同batch就得重新轉(zhuǎn)換非常麻煩。第三導(dǎo)出的模型里盡量不要包含自定義算子、數(shù)據(jù)依賴的循環(huán)結(jié)構(gòu)這類(lèi)ONNX算子QNN不一定認(rèn)識(shí)一旦遇到就只能改成標(biāo)準(zhǔn)算子或者提前把邏輯拆到C里做預(yù)處理。我踩過(guò)最大的坑是模型里有一個(gè)torch.where的條件分支導(dǎo)出ONNX之后轉(zhuǎn)換器總是報(bào)算子不支持。后來(lái)把網(wǎng)絡(luò)結(jié)構(gòu)里的動(dòng)態(tài)條件邏輯挪到前處理步驟中用mask加法代替條件分支才順利轉(zhuǎn)換成功。所以導(dǎo)出模型之前最好先檢查一遍網(wǎng)絡(luò)里有沒(méi)有比較冷門(mén)的高級(jí)操作。2.3 使用qnn-onnx-converter的完整轉(zhuǎn)換命令環(huán)境變量配置好之后用轉(zhuǎn)換器把ONNX轉(zhuǎn)成QNN模型描述文件python $QNN_SDK_ROOT/bin/qnn-onnx-converter \ --input_network model.onnx \ --output_qnn_path ./qnn_model \ --input_list ./input_list.txt \ --quantize_full_type_uint16input_list.txt是用于校準(zhǔn)的數(shù)據(jù)列表每一行寫(xiě)一個(gè)數(shù)據(jù)文件的路徑。這些數(shù)據(jù)文件是原始輸入通常是二進(jìn)制格式或者npy格式。如果你要做全整型量化校準(zhǔn)數(shù)據(jù)必須覆蓋真實(shí)場(chǎng)景的分布比如輸入是圖片最好從驗(yàn)證集里隨機(jī)抽200~500張盡量包含各種光照、角度、遮擋情況。校準(zhǔn)數(shù)據(jù)如果太單調(diào)量化后的模型精度會(huì)有明顯崩塌。--quantize_full_type_uint16表示權(quán)重激活都用uint16量化這是HTP上常用的一種方案精度比uint8高一些性能差異也不大。如果你追求極致性能可以試試uint8但精度掉得比較厲害。這塊可以多測(cè)幾組找一個(gè)準(zhǔn)確率和速度的平衡點(diǎn)。轉(zhuǎn)換完會(huì)在qnn_model目錄下生成一個(gè)model.serialized描述文件。接下來(lái)用Context Binary生成器把描述文件和HTP Backend綁定qnn-context-binary-generator \ --backend $QNN_SDK_ROOT/lib/aarch64-unknown-linux-gnu/libQnnHtp.so \ --model qnn_model/model.serialized \ --binary_file model_context.bin生成的model_context.bin就是最終要部署到設(shè)備上的文件。注意這里指定的libQnnHtp.so是開(kāi)發(fā)機(jī)上的x86版本還是目標(biāo)板子的ARM版本命令行里的庫(kù)路徑實(shí)際上會(huì)被運(yùn)行時(shí)路徑替代生成的Context Binary里記錄的是一些后端圖信息最終執(zhí)行還是在設(shè)備的HTP上所以選哪個(gè)版本不是最核心的問(wèn)題。但為了保險(xiǎn)我一般還是用目標(biāo)架構(gòu)的路徑去生成省得后續(xù)出現(xiàn)莫名其妙的ABI不兼容。2.4 用qnn-model-tool檢查模型信息轉(zhuǎn)換完之后不要急著寫(xiě)C代碼先用高通自帶的工具檢查一下生成結(jié)果qnn-model-tool --model model_context.bin --print_info這個(gè)命令會(huì)打印模型的輸入輸出張量名稱(chēng)、維度和類(lèi)型。我會(huì)把輸入張量的名字記下來(lái)后面C代碼里創(chuàng)建張量時(shí)要用這個(gè)名字去匹配。如果名字寫(xiě)錯(cuò)了graphExecute的時(shí)候通常會(huì)報(bào)張量未綁定或者數(shù)據(jù)填充失敗的錯(cuò)。另外還可以用qnn-model-tool --model model_context.bin --print_buffers查看模型內(nèi)所有緩沖區(qū)的布局方便確認(rèn)輸入數(shù)據(jù)應(yīng)該按什么形狀填充。這一步雖然簡(jiǎn)單但能避免后面代碼里到處猜維度。3. 手寫(xiě)C推理代碼核心調(diào)用步驟逐段拆解環(huán)境搞定、模型轉(zhuǎn)換完成現(xiàn)在進(jìn)入重頭戲C調(diào)用QNN SDK。我用一個(gè)最簡(jiǎn)單的圖像分類(lèi)模型做例子把從加載模型到推理輸出的整個(gè)流程寫(xiě)成代碼。這個(gè)結(jié)構(gòu)也可以直接套用到檢測(cè)、分割等更復(fù)雜的模型上。3.1 核心接口說(shuō)明QNN SDK的C接口核心其實(shí)就是一組函數(shù)指針表通過(guò)QnnInterface_getProviders()拿到接口提供者再?gòu)奈锢碓O(shè)備加載Backend實(shí)現(xiàn)初始化之后就能使用它提供的能力。QNN最大的特點(diǎn)是把Backend和Context分開(kāi)抽象Backend是物理能力層負(fù)責(zé)管理NPU/GPU/DSP資源Context是邏輯執(zhí)行層負(fù)責(zé)持有模型圖和內(nèi)部狀態(tài)。整個(gè)調(diào)用序列可以分成四步獲取QNN接口初始化Backend。用導(dǎo)入的Context Binary創(chuàng)建Context。從Context中獲取Graph并綁定輸入輸出張量。執(zhí)行推理讀取結(jié)果。代碼寫(xiě)起來(lái)會(huì)有一些宏和版本差異但接口骨架非常穩(wěn)定。下面我會(huì)拆成幾個(gè)代碼塊來(lái)解析。3.2 從QNN Backend初始化到加載Context Binary先看接口獲取和初始化的代碼#include QnnInterface.h #include QnnTypes.h #include QnnContext.h #include QnnGraph.h #include QnnTensor.h #include iostream #include vector #include cstring #include fstream #include dlfcn.h using QnnFunctionTable QNN_INTERFACE_VER_TYPE; QnnFunctionTable* g_qnn nullptr; Qnn_BackendHandle_t g_backend nullptr; Qnn_ContextHandle_t g_context nullptr; bool loadQnnInterface(const char* backendLibPath) { void* handle dlopen(backendLibPath, RTLD_NOW | RTLD_GLOBAL); if (!handle) { std::cerr dlopen failed: dlerror() std::endl; return false; } auto getProviders (Qnn_ErrorHandle_t (*)(const QnnInterface_t***, uint32_t*)) dlsym(handle, QnnInterface_getProviders); if (!getProviders) { std::cerr cannot find QnnInterface_getProviders std::endl; return false; } const QnnInterface_t** providers nullptr; uint32_t numProviders 0; if (getProviders(providers, numProviders) ! QNN_SUCCESS || numProviders 0) { std::cerr no QNN providers found std::endl; return false; } g_qnn providers[0]-QNN_INTERFACE_VER_TYPE; return true; }dlopen那一步就相當(dāng)于在運(yùn)行時(shí)加載HTP驅(qū)動(dòng)的前端庫(kù)。為什么要用dlopen而不是直接鏈接因?yàn)槟憧梢酝ㄟ^(guò)命令行參數(shù)傳入不同的Backend庫(kù)路徑程序變得更靈活。想切到GPU Backend時(shí)只需要換個(gè)路徑即可不用重新編譯。拿到接口之后開(kāi)始初始化Backend和Contextbool initBackendAndContext(const std::string modelPath) { if (!g_qnn) return false; // 初始化后端 if (g_qnn-backendInitialize(nullptr) ! QNN_SUCCESS) { std::cerr backend initialize failed std::endl; return false; } // 創(chuàng)建后端句柄 Qnn_Backend_Config_t* backendConfig nullptr; if (g_qnn-backendCreate(nullptr, backendConfig, g_backend) ! QNN_SUCCESS) { std::cerr backend create failed std::endl; return false; } // 讀取Context Binary內(nèi)容 std::ifstream binFile(modelPath, std::ios::binary); std::vectoruint8_t buffer((std::istreambuf_iteratorchar(binFile)), std::istreambuf_iteratorchar()); if (buffer.empty()) { std::cerr model binary is empty std::endl; return false; } // 從二進(jìn)制直接創(chuàng)建Context Qnn_Context_Config_t contextConfig; memset(contextConfig, 0, sizeof(contextConfig)); Qnn_ContextCreateFromBinary_Config_t* ctxCreateConfig nullptr; if (g_qnn-contextCreateFromBinary( g_backend, nullptr, buffer.data(), buffer.size(), g_context, ctxCreateConfig) ! QNN_SUCCESS) { std::cerr context create from binary failed std::endl; return false; } return true; }這里要解釋一下為什么用contextCreateFromBinary而不是contextCreate。contextCreate要求傳入網(wǎng)絡(luò)描述符運(yùn)行時(shí)再?gòu)拿枋龇麡?gòu)建圖。而contextCreateFromBinary接收的是離線生成好的二進(jìn)制執(zhí)行計(jì)劃所有算子的選擇、內(nèi)存分配、依賴關(guān)系都已經(jīng)確定。路徑短、開(kāi)銷(xiāo)小、穩(wěn)定可靠這就是上一章極力推薦Context Binary的原因。執(zhí)行完以上代碼模型其實(shí)已經(jīng)在HTP上初步建立了執(zhí)行上下文但還缺輸入輸出張量這塊拼圖。3.3 創(chuàng)建輸入輸出Tensor并填充數(shù)據(jù)張量在QNN里是一個(gè)非常重要的抽象它描述了一塊數(shù)據(jù)區(qū)以及它的維度、數(shù)據(jù)類(lèi)型、量化參數(shù)等信息。創(chuàng)建張量的代碼如下bool createInputTensor(const std::string name, const std::vectoruint32_t dims, Qnn_Tensor_t tensor) { tensor QNN_TENSOR_INIT; tensor.type QNN_TENSOR_TYPE_APP_WRITE; // 輸入張量由應(yīng)用寫(xiě)入 tensor.dataFormat QNN_TENSOR_DATA_FORMAT_FLOAT_32; Qnn_TensorData_t td tensor.tensorData; td.name name.c_str(); td.rank static_castuint32_t(dims.size()); td.dimensions const_castuint32_t*(dims.data()); td.dataType QNN_DATATYPE_FLOAT_32; td.quantizeParams.encodingDefinition QNN_TENSOR_QUANTIZATION_NONE; if (g_qnn-tensorCreate(g_context, tensor) ! QNN_SUCCESS) { std::cerr tensor create failed: name std::endl; return false; } return true; }QNN_TENSOR_TYPE_APP_WRITE表示這塊內(nèi)存在設(shè)備端由應(yīng)用側(cè)負(fù)責(zé)寫(xiě)入。還有一種常見(jiàn)類(lèi)型是QNN_TENSOR_TYPE_APP_READ用于輸出張量表示應(yīng)用需要從設(shè)備端讀取結(jié)果。當(dāng)然也有QNN_TENSOR_TYPE_NATIVE這類(lèi)直接綁定設(shè)備內(nèi)存的用法但那是性能優(yōu)化階段才需要考慮的事第一次跑通流程時(shí)先用APP_WRITE/APP_READ最省心。創(chuàng)建完輸入張量后要把圖像數(shù)據(jù)填進(jìn)去void fillInputTensor(Qnn_Tensor_t tensor, const std::vectorfloat imageData) { // 先讓QNN獲取一塊可寫(xiě)入的數(shù)據(jù)指針 void* tensorData nullptr; g_qnn-tensorGetData(tensor, tensorData); if (tensorData nullptr) { std::cerr input tensor data pointer is null std::endl; return; } memcpy(tensorData, imageData.data(), imageData.size() * sizeof(float)); }輸出張量的創(chuàng)建邏輯類(lèi)似但type要改成QNN_TENSOR_TYPE_APP_READ。這里的核心概念是QNN的輸入輸出張量本質(zhì)上是共享內(nèi)存的通道你往輸入張量綁定的指針里寫(xiě)數(shù)據(jù)模型執(zhí)行時(shí)直接讀這塊內(nèi)存執(zhí)行結(jié)束后從輸出張量綁定的指針里取數(shù)據(jù)。把數(shù)據(jù)搬進(jìn)去和取出來(lái)是整個(gè)流程唯一需要顯式操作內(nèi)存的地方。3.4 執(zhí)行推理和結(jié)果讀取執(zhí)行推理是整個(gè)項(xiàng)目最爽的一步代碼反而是所有環(huán)節(jié)里最簡(jiǎn)短的bool runInference(Qnn_Tensor_t inputTensor, Qnn_Tensor_t outputTensor) { // 獲取模型中的圖句柄 Qnn_GraphHandle_t graphHandle nullptr; Qnn_GraphHandle_t* graphList nullptr; uint32_t numGraphs 0; if (g_qnn-contextGetGraphs(g_context, graphList, numGraphs) ! QNN_SUCCESS) { std::cerr context get graphs failed std::endl; return false; } if (numGraphs 0) { std::cerr no graph in context std::endl; return false; } graphHandle graphList[0]; // 將輸入輸出張量綁定到執(zhí)行 Qnn_Tensor_t tensors[2] { inputTensor, outputTensor }; if (g_qnn-graphExecute(graphHandle, tensors, 2, nullptr, nullptr) ! QNN_SUCCESS) { std::cerr graph execute failed std::endl; return false; } // 讀取輸出數(shù)據(jù) void* outData nullptr; g_qnn-tensorGetData(outputTensor, outData); float* floatOut reinterpret_castfloat*(outData); std::cout Inference done. First 10 outputs: std::endl; for (int i 0; i 10; i) { std::cout floatOut[i] ; } std::cout std::endl; return true; }graphExecute的執(zhí)行是同步的調(diào)用返回時(shí)推理就已經(jīng)完成了。如果你做的是視頻流或者連續(xù)多幀處理建議在創(chuàng)建Context時(shí)打開(kāi)異步執(zhí)行相關(guān)的配置改成邊采集邊推理的方式提升吞吐。后面章節(jié)會(huì)展開(kāi)說(shuō)。一個(gè)容易忽略的細(xì)節(jié)是contextGetGraphs拿到的圖句柄列表是Context內(nèi)部的不需要自行釋放。如果你加載的Context Binary里包含了多個(gè)模型比如一個(gè)檢測(cè)模型加一個(gè)特征模型遍歷這個(gè)數(shù)組就能拿到所有圖句柄分別執(zhí)行。實(shí)際項(xiàng)目中很有用。3.5 資源釋放的正確順序資源釋放順序有講究別小看這最后一步。一個(gè)常見(jiàn)的錯(cuò)誤是先把Backend銷(xiāo)毀了再銷(xiāo)毀Context然后程序崩潰。正確的順序是void cleanup() { if (g_context) { g_qnn-contextFree(g_context); g_context nullptr; } if (g_backend) { g_qnn-backendFree(g_backend); g_backend nullptr; } // 后端terminate放最后 g_qnn-backendTerminate(nullptr); }先釋放Context再釋放Backend最后調(diào)用backendTerminate。原因很簡(jiǎn)單Context還持有Backend內(nèi)部的設(shè)備資源如果先把Backend釋放掉Context在銷(xiāo)毀的時(shí)候會(huì)訪問(wèn)到一塊已經(jīng)失效的句柄區(qū)域輕則告警重則段錯(cuò)誤。我早期做這塊時(shí)都是直接不釋放進(jìn)程退出讓系統(tǒng)回收后來(lái)做長(zhǎng)時(shí)間運(yùn)行的服務(wù)才發(fā)現(xiàn)釋放順序混亂會(huì)導(dǎo)致內(nèi)存持續(xù)上漲最后只能把進(jìn)程重啟。養(yǎng)成正確的釋放習(xí)慣寫(xiě)出來(lái)的服務(wù)才敢跑上幾天幾夜。4. 編譯運(yùn)行與踩坑實(shí)錄從代碼到真正跑起來(lái)代碼寫(xiě)完之后編譯和運(yùn)行階段才是真正開(kāi)始“打仗”的時(shí)候。這一章我把高頻踩坑點(diǎn)整理出來(lái)希望能幫你從報(bào)錯(cuò)大海里快速爬出來(lái)。4.1 編譯期錯(cuò)誤怎么排查編譯命令大致是這樣aarch64-linux-gnu-g -stdc17 qnn_runner.cpp -o qnn_runner \ -I$QNN_SDK_ROOT/include \ -L$QNN_SDK_ROOT/lib/aarch64-unknown-linux-gnu \ -Wl,-rpath,$QNN_SDK_ROOT/lib/aarch64-unknown-linux-gnu這里重點(diǎn)說(shuō)一下-Wl,-rpath的作用。編譯時(shí)鏈接的庫(kù)在運(yùn)行時(shí)也要能被找到如果你不在編譯時(shí)指定rpath運(yùn)行前就必須手動(dòng)設(shè)置LD_LIBRARY_PATH。跑服務(wù)的時(shí)候很容易忘記設(shè)置然后看到一連串error while loading shared libraries排查半天才發(fā)現(xiàn)是動(dòng)態(tài)庫(kù)路徑問(wèn)題。把它編進(jìn)二進(jìn)制里一勞永逸。編譯期最常遇到的第一類(lèi)報(bào)錯(cuò)是找不到頭文件比如fatal error: QnnType.h: No such file or directory。這通常是-I路徑寫(xiě)錯(cuò)了檢查一下SDK里的include目錄結(jié)構(gòu)把路徑對(duì)準(zhǔn)包含QnnInterface.h的那一層。第二類(lèi)報(bào)錯(cuò)是鏈接時(shí)找不到QnnInterface_getProviders符號(hào)報(bào)undefined reference。多半是因?yàn)槟阌昧薈編譯器但接口頭文件里的函數(shù)沒(méi)有用extern C包裹。QNN頭文件有的版本自帶兼容處理有的版本則需要在包含前手動(dòng)加上extern C { #include QnnInterface.h }這個(gè)問(wèn)題很隱蔽因?yàn)榫幾g器報(bào)錯(cuò)行號(hào)往往指向你的源文件而不是頭文件讓人誤以為是自己代碼寫(xiě)錯(cuò)了。后來(lái)我在項(xiàng)目規(guī)則里固定了一條所有QNN相關(guān)頭文件一律用extern C包含從此再?zèng)]遇到過(guò)這類(lèi)鏈接問(wèn)題。4.2 運(yùn)行時(shí)錯(cuò)誤速查表運(yùn)行時(shí)錯(cuò)誤五花八門(mén)把幾個(gè)高頻場(chǎng)景列成表格方便對(duì)照排查現(xiàn)象常見(jiàn)原因處理建議dlopen失敗libQnnHtp.so: cannot open shared object fileLD_LIBRARY_PATH沒(méi)指對(duì)或者庫(kù)架構(gòu)不匹配先確認(rèn)當(dāng)前運(yùn)行的機(jī)器架構(gòu)再設(shè)置對(duì)應(yīng)的庫(kù)路徑backendCreate返回錯(cuò)誤沒(méi)有更多日志HTP固件版本和SDK版本不匹配檢查設(shè)備的DSP固件版本升級(jí)Hexagon SDK或更換QNN版本contextCreateFromBinary報(bào)RPC_ERRORHTP驅(qū)動(dòng)沒(méi)加載或者權(quán)限不足確認(rèn)設(shè)備端是否已經(jīng)啟動(dòng)QNN的RPC服務(wù)用高通提供的run工具初始化環(huán)境輸入張量數(shù)據(jù)寫(xiě)不進(jìn)去tensorGetData返回空指針張量類(lèi)型設(shè)置錯(cuò)誤用了NATIVE類(lèi)型卻沒(méi)有綁定設(shè)備內(nèi)存首次跑通流程用QNN_TENSOR_TYPE_APP_WRITEgraphExecute崩潰提示張量名稱(chēng)不匹配代碼里創(chuàng)建張量的名字和模型里不一致用qnn-model-tool --print_info查看模型真實(shí)張量名推理結(jié)果全是0輸入數(shù)據(jù)沒(méi)寫(xiě)進(jìn)張量或者量化參數(shù)設(shè)置不對(duì)先用float模型跑通再切量化模型對(duì)比結(jié)果這里補(bǔ)充一個(gè)容易忽略的點(diǎn)如果設(shè)備上跑的是沒(méi)有root權(quán)限的用戶態(tài)進(jìn)程訪問(wèn)HTP可能會(huì)被SELinux或者權(quán)限策略攔下來(lái)報(bào)一些看起來(lái)完全莫名其妙的錯(cuò)誤。遇到這類(lèi)問(wèn)題先檢查日志看有沒(méi)有權(quán)限相關(guān)的關(guān)鍵字。沒(méi)有權(quán)限就用系統(tǒng)管理員協(xié)助調(diào)整配置不要試圖硬繞權(quán)限限制。4.3 打開(kāi)日志和調(diào)試技巧QNN內(nèi)部有一套完整的日志機(jī)制調(diào)試的時(shí)候打開(kāi)日志能幫你少走很多彎路。export QNN_LOG_LEVELVERBOSE ./qnn_runner日志級(jí)別從低到高通常是ERROR、WARN、INFO、VERBOSE。平時(shí)跑服務(wù)用WARN就行檢查問(wèn)題時(shí)開(kāi)到VERBOSE。開(kāi)啟后你會(huì)看到SDK內(nèi)部每一步在做什么比如加載后端、創(chuàng)建Context、綁定張量、執(zhí)行算子。有一次模型執(zhí)行結(jié)果不對(duì)打開(kāi)日志才發(fā)現(xiàn)是某些算子在HTP上走了低精度分支數(shù)值精度下降導(dǎo)致結(jié)果偏差但整個(gè)流程本身沒(méi)有報(bào)錯(cuò)。這種問(wèn)題不開(kāi)日志根本無(wú)從查起。還有一個(gè)小技巧在代碼里加一個(gè)getElapsedTime的計(jì)時(shí)模塊分別統(tǒng)計(jì)模型加載耗時(shí)和推理耗時(shí)。模型加載耗時(shí)可以用來(lái)判斷Context Binary是否真的被完整加載推理耗時(shí)可以判斷模型是否真的跑在了HTP上。如果推理耗時(shí)和純CPU實(shí)現(xiàn)差不多那就要懷疑是不是量化沒(méi)生效或者Backend配置里禁用了HTP加速。4.4 如何確認(rèn)推理真的跑在HTP上這里插一個(gè)重要驗(yàn)證步驟怎么確認(rèn)模型不是跑在CPU上最簡(jiǎn)單的方法是看執(zhí)行時(shí)間。一個(gè)MobileNetV2量化的模型在驍龍8系列平臺(tái)上跑推理時(shí)間通常只有幾毫秒如果代碼配置正確肉眼可見(jiàn)地比純CPU快。另一種方式是在QNN日志里搜索HtpGraph之類(lèi)的關(guān)鍵字VERBOSE日志會(huì)打印出后端執(zhí)行時(shí)的算子調(diào)度信息。更嚴(yán)謹(jǐn)?shù)淖龇ㄊ菍?shí)測(cè)功耗。把設(shè)備插上功率計(jì)跑100次推理對(duì)比CPU版和HTP版的功耗差異。HTP版本通常明顯更低。做功耗對(duì)比的時(shí)候建議把屏幕亮度、無(wú)線模塊等因素固定住否則數(shù)據(jù)會(huì)被干擾帶偏。日志確認(rèn)和功耗測(cè)量都做過(guò)之后基本可以放心你的模型已經(jīng)真正跑在高通NPU上了。5. 性能優(yōu)化與落地建議到這里整個(gè)流程已經(jīng)跑通了模型能夠在C程序里被加載和推理。但跑通只是第一步要想真正落地到產(chǎn)品里還有幾個(gè)關(guān)于性能和穩(wěn)定性的問(wèn)題需要處理。這部分不是必選項(xiàng)但對(duì)于做長(zhǎng)期項(xiàng)目的人來(lái)說(shuō)非常值得參考。5.1 Tensor內(nèi)存分配與對(duì)齊前面提到APP_WRITE/APP_READ張量類(lèi)型最省心但在追求極致性能時(shí)可以考慮使用QNN_TENSOR_TYPE_NATIVE并把輸入輸出緩沖區(qū)直接綁到設(shè)備端。這種做法的好處是省去了Host和Device之間的一次內(nèi)存拷貝。如果決定用原生內(nèi)存綁定的方式就必須注意內(nèi)存對(duì)齊。QNN的HTP后端對(duì)緩沖區(qū)有對(duì)齊要求通常是256字節(jié)或者更高具體值可以在SDK的文檔中查到。用posix_memalign分配內(nèi)存設(shè)置QNN_TENSOR_MEM_TYPE_DMA等類(lèi)型再通過(guò)tensorCreateCustom綁定能明顯降低單次推理的負(fù)載。不過(guò)這屬于進(jìn)階優(yōu)化第一次做項(xiàng)目不建議直接上。先用APP_WRITE/APP_READ把功能做對(duì)之后再用性能剖析工具找出真正的瓶頸點(diǎn)再有針對(duì)性地替換成原生內(nèi)存方案。5.2 Context復(fù)用與多模型切換在一個(gè)長(zhǎng)期運(yùn)行的應(yīng)用里不要每推理一幀就創(chuàng)建一個(gè)新Context這是非常浪費(fèi)的。一個(gè)Context可以復(fù)用很多次graphExecute是線程安全還是需要加鎖取決于具體后端實(shí)現(xiàn)但通常建議一個(gè)Context對(duì)應(yīng)一個(gè)推理線程保持穩(wěn)定的調(diào)用頻率。多線程場(chǎng)景下要么給Context加鎖要么創(chuàng)建多個(gè)Context每個(gè)線程持有一個(gè)后者吞吐更好。如果你有多個(gè)模型需要切換推理可以一次性把所有模型的Context Binary都加載進(jìn)來(lái)每個(gè)模型對(duì)應(yīng)一個(gè)Context和一組輸入輸出張量。執(zhí)行時(shí)按需調(diào)用對(duì)應(yīng)Context的圖切換開(kāi)銷(xiāo)很小。這種設(shè)計(jì)比每次切換都創(chuàng)建銷(xiāo)毀Context要穩(wěn)得多內(nèi)存占用也更好預(yù)估。5.3 我的個(gè)人維護(hù)習(xí)慣最后分享一個(gè)我自己的習(xí)慣每跑通一個(gè)新模型就在項(xiàng)目目錄下新建一個(gè)model_config.txt把模型版本、輸入尺寸、量化方案、Backend庫(kù)版本、生成Context Binary的命令全部記錄下來(lái)。這東西看機(jī)器折騰久了半年后回來(lái)看項(xiàng)目如果沒(méi)有一份配置記錄你會(huì)對(duì)著一個(gè)陌生模型文件發(fā)半天呆。我看過(guò)太多人拿著別人給的Context Binary直接接進(jìn)業(yè)務(wù)代碼出了問(wèn)題不知道是后端不兼容還是模型轉(zhuǎn)換有誤只能從頭排查。提前把版本信息記錄好配合上面說(shuō)的日志分級(jí)機(jī)制排查問(wèn)題基本能砍掉一半時(shí)間。QNN整套東西上手之后會(huì)發(fā)現(xiàn)它的接口設(shè)計(jì)一旦理順剩下的就是機(jī)械式調(diào)用。真正決定項(xiàng)目上限的反而是在模型轉(zhuǎn)換階段對(duì)算子兼容性的把握以及在C側(cè)對(duì)張量生命周期的管理能力。第一次跑通別著急上性能優(yōu)化先讓整個(gè)鏈路穩(wěn)定轉(zhuǎn)起來(lái)再一步步打磨細(xì)節(jié)。
返回列表
PREV
查看更多資訊
NEXT
返回資訊列表
久操凹凸视频| 国产男女无套视频免费观看| 亚洲熟久久| www成人啪啪18秘 免费| 欧美精品23| 九九热精品视频六| 国产精品人妻无码久久久互動交流| 美女人妻色网站| 一区三区啪啪| 91干熟女| 免费看日本操逼视频| 美国黄片aaa| 啊啊啊好多水| 97爱爱官网| 丝袜视频一区二区在线播放国产中文| 亚洲色图超碰在线| 激情开心五月天| 欧美性爱www免费版| 欧美亚洲| 国产精品九九九| 2019天天干| 青青草综合在线| 东方亚洲在线操逼天堂| 中文字幕超碰CAO| 欧美午夜精品久久久久久超碰| 成人七区| 福利伊人玖玖国产| 色哟哟511老熟女| 亚洲国产成人精品久久久国产成人一区二区 | 熟女一区二区三区| 国产久久日韩网站导航| 亚洲人综合| 啊啊啊不要嗯嗯在线观看| 欧洲中文字幕| 97超碰在线资源网站| 亚洲国产欧美日韩精品一区二区三区,国产一区二区三区在线看片,欧美性猛交 XXX | 日韩九九九| 超碰在线91| 人妻丝袜日本| 欧美不卡在线一区二区| 7777奇米影视久久| 亚洲va有码在线天堂| 丝袜剧情| 伊人久久婷婷| 久久精品视频久久久| 亚洲天天艹| 97色插| 67914亚洲精品| 粉嫩国产精品久久久| 夜夜騷av、一區二區| 亚洲精品久久久久久久久豆丁网| 久久久久久久极品香蕉视频| 欧美 熟女 日韩| 天天操天天7| 天天日骚逼熟女| 老熟乱一区二区三区四区| 精品天堂| 2020中文在线一区二区三区| 伊人久久88国产女| 干b在线性社区| 国产精品色哟哟| 国产精品午夜成人福利| 青木玲在线不卡| 丝袜视频网国产90| 东京热男人的天堂| 中文字幕免费看大片| 99日精品欧美国产| 天天爽夜夜欢视| 96精品一区| 97国产精品视频| 手机在线免费看的av| 口爆吞精在线观看| 大奶尤物鲍汁淫荡欧美视频粉嫩夜夜骚 | 亚洲色图第一页| 躁躁躁日日躁2020| 国产精品一级片在线看| 国产精品交换一区二区| 亚洲国产中文字幕| 亚洲成人久久一区二区| 国产免费大片| 97色欧洲| 麻豆 欧美 日韩| 97硬碰| 天天色播亚洲综合网站| 色狠人在线99| 天美av在线观看| 日本超碰97日韩精品人妻| 0755午夜福利视频| 午夜啪啪片| 色久综合| 欧美色交| AAAAAAAAA黄片| 精品在线78| 久久一区二区三区四区五区| 7777欧美成是人在线观看| 亚洲色悠悠久久88| 久久av成人无码免费| 激情综合五月天| 青青草玖玖爱| 日韩欧美tv一区二区在线观看| 91一起操| 日韩欧无码一区二区三区免费不卡 | 亚洲欧美91| 99久久婷婷丁香| 少妇毛片久久| 91亚洲人| 电影69乱码96| 97天堂| 亚洲综合九九| 午夜九九| 精品超碰国产| 亚洲色人阁| 亚洲国产ⅴ高清在线观看| 91黑丝在线播放| 亚洲激情深爱文学小说网站| 精品国产肉丝袜在线拍国语| 色狠狠一区二区三区香蕉| 殴美在线AⅤ| 一区二区不卡免费| 久久无码电影| 亚洲图片第一页| 91精品久久久久久77777| 97久操| 极品白嫩美女白浆成人福利在线看| 日日黄色三级网站| 欧美熟女操屄| 蜜桃臀久久| 婷婷五月天激情网| 男女啊啊啊啊啊| www99热| 99热这里只有精品18| 嗯嗯啊啊啊啊轻点视频| 国产成人精品必看| 91超碰碰在线| 乱伦系列一区二区| 亚洲成人在线乱码色午夜| 人人摸人人干人人拍97| 91久热| 五月婷婷大香蕉| 蜜臀在线视频| 老汉网| 天天躁日日躁成人字幕aⅴ| 五月丁香色综合| 亚洲av青草久久一区二区| 91久久久久久久久久久| 99这里只有精品国产| 婷婷丁香五月天综合东京热| 亚洲青色欧美| 亚洲高清自拍| 亚洲精品欧美专业| 国内亚洲精彩视频在线| 91n处女在线观看| 日韩偷拍色图| 久久久久久久国产a∨| 色香网| 亚洲nv男人的天堂网| 18禁看网站一区| 亚洲少妇在线影音| 天天欧美色| 99国产精品视频尤物| 欧美丝袜91| 亚洲加勒比| 天美一二三在线观看Av| 欧美日韩性感| 精品一区二区成人动漫| 2017人人操,人人摸| 97久久天天综合色天天综合色电影| 色情五月丁香| 国产成人自拍视频在线| 一区不卡在线观看av| 国产日韩中文字幕欧美| 精品人妻无码一区二区三区不卡-精品人妻无码一区二区...|精品少妇一区二区三 | 欧美色欧美| 欧美色综合图片| 婷婷色综合| 亚洲av综合色区无码一| 亚洲免费在线探花| 中文字幕精品丝袜| 人妻少妇被猛烈进入中| 97综合国产| 熟妇一区,二区,三区。| AV色五月天| 一区二区三区 丝袜 高跟 美腿| 亚洲国产91精品一区二区久久| 97天天日| 亚洲综合九九| 啪啪自拍九九综合| 欧美色亚洲| 亚洲欧洲综合| 久操免费视频| 无码人妻一区二区三区四区老鸭窝| 精品人妻一区春色| 99re99视频在线免费观看| 熟女性视频| 色香色欲天天综合网天天来吧| 一区二区三区在线美女| 青青操网| 成人性爱av| 91精品人妻偷情| 欧美第一页| 亚洲夜夜欢无码一区二区 | 综合久久欧美| 久久久国产成人一区二区三区在线| 国产一级高跟丝袜| 男女日B国产| 97在线免费观看| 91丰满| 99视频自拍区| 欧美在线天堂| 久热一区二区| 97欧美超碰| 97久久超碰| 日韩三级伊人| 另类TS人妖一区二区三区 | 男人网站婷婷| 男人天堂网手机版婷婷| 亚洲色婷婷综合久久一区二区三区| 少妇蹲下买菜露大唇0| 天堂av最新电影网| 男人久久天堂| 99re热有精品视频国产| 天堂8在线新版官网| 日本韩欧美在线播放a| 巨爆乳肉感一区二区三区竹菊影视| 深夜激情无码| 口爆综合网| 视频在线观看一二三区| 日韩精品第3页| 欧美日动态视频| 激情婷婷丁香| 啊啊啊久久| 日本性交操一区二区不卡系列| 久久久精品中文字幕爱豆| 久久久久久久久久久免费精品| 一类无码操逼视频| 26uuu国产| 夜夜操av亚洲一区二区| 在线色资源| 国产精品天堂| 3p国产色噜噜一区| 99.色网| 91激情网| 啊啊嗯嗯好爽| 欧美人妻精品一区二区| 99激情| 亚洲视频一二区| 91亚洲欧美综合高清在线| 天堂性色| 深夜国产一区二区三区在线看| 日韩AV一起草| 久久97超碰香蕉| 九九久久玖玖| 久热91| 黑人中出21连凳花野真衣| 日韩中文字幕宗合在线| 欧美性xxxxx狂欢| 国产精品婬乱一级毛片彝族| 你操综合| 日韩一卡二卡三卡| 操操操日本的逼| 欧美日韩性感| 91色欧美| JULIA一区二区三区在线播放| 91人人爽人人爽| 综合色久欲| AV一起草在线| 蜜桃传媒一区二区亚洲| 天干天干天干天天做| 综合国产影视三级| 国内精品久久国产,www香蕉久久五月丁香,亚洲欧美日韩精品永久在线,日本精品一 | 日本不卡五区| 九九九九久久久| 韩国毛片一区二区三区| 久久精品国产亚洲AV无码电影| 精品无码久久久| 欧美丝袜中文字幕07在线| 国产日韩精品人妻久久久久色欲网站 | 91久久久久久久| 视频国产成人精品日本亚洲18| 色五月激情网| 日韩内| 综合色99| 天天噜| 亚洲在线综合| 欧美亚洲日本视频久久久| 91在线免费观看处女| 天天综合色图| 色综合五月天| 九色黄站| 亚洲国产欧美日韩精品一区二区三区,国产一区二区三区在线看片,欧美性猛交 XXX | 欧美三级不卡| 内射小黄片| 国产精品天美传媒| 精品九九九| 久久综合18p| 亚洲在饯| 日韩紧密久久| 秋霞网—男女啪啪亚洲免费体验区| 色噜噜人妻av 中文字幕| 97色色色| 亚洲AV乱码专区国产噜噜亚洲| 亚洲欧美不卡线| 亚洲 日本 一 二 三| 超碰97国产欧美| caorenqi shipin| 日本一区二区不卡| 欧美 综合| 国产精品自拍xxxx| 亚洲欧美校园| 婷婷五月天av| 色老牛| 日日插夜夜| 超碰这里只有精品| 草莓精品视频| 欧美色图91| 91色碰| 日韩免费福利在线观看| 欧洲精品久久| 色穴精品| 日韩精品 视频一区二区| 国产又粗又长的视频| 色综合天天| 国产免费黄色一级大片| 中文字幕人乱码中文字的预防方法 | 一区AV| 青青草男人天堂| aaa一级黄片| 成年人黄色| 欧美爆操91| 欧美强奸乱| 9久久久久| 国产成人主播| 蜜桃视频精品一区二区| 国产成人99久久亚洲综合| 为用户提供免费看黄网址在线观看| 国产精品国产| 久久久精品国产亚洲伊人| 蜜乳成人AV| 中文字幕视频免费| 亚洲欧美第一页| 怡春苑东京热| 中国操逼无码| 欧美色日本| 久/久精品99看9| 强奸抽插av| 超碰97亚洲区| 欧美欲色| 亚洲国产欧美日韩人妻日中文| 久久男人精品| 超碰95| 九九九草| 日本中文字幕一区| 媚薬在线视频麻豆| 国产日韩精品一区二区三区| 亚洲av淫乱| 中文字幕 一区二区 亚洲无码| 看免费一级在线播放毛片| 色欧洲97| 91黑丝美女| 天天日日夜夜| a在线视频免费观看| 欧美日产国产在线成人第一区| 在线看污网站| 麻豆天美AV传媒第一页| 亚洲激情色片 | 成年在线视频日本亚洲在线视频区精品江靖宇公司 | 亚洲码在线中文在线观看| 欧洲精品二区| 亚洲色欧美| 台湾佬大香蕉| 久一区久久蜜桃| 亚洲资源一区| 欧美黑人熟妇精品91| 天天夜夜rb| 亚洲午夜蜜臀| 欧美日韩国产色图在线| 亚洲乱色熟女一区| 精品亚洲国产成人精品| 亚洲精品国产日韩无码AV永久免 | 久热这里| 爱射综合| 桃色六月天| 色月天AV导航| 91久久18禁| 91天天爱| 天天日美女的B| 另类视频在线| 91网站18+| 亚洲精品人伦一区二区| 亚洲色欧| 精品传媒在线一区| 色综合加勒比| 中文人妻av高清一区| 精品久久久久久中文字幕三区| 黑人精品XXX一区一二区| 日本中文熟女视频| 国产免a费看黄片在线| 亚洲国产成人福利在线观看| 欧美极度丰满熟妇hd| 99久久网站| 亚洲 欧美都市激情| 欧美在线官网| 果冻传媒一区二区三区| 无码精品蜜桃一区二区三区ww| 亚洲第一黄色av网站| 午夜福利免费精品视频| 女优视频第10页| 欧美狠狠操| 日本黄色天堂| 天天澡天天爽日日AV| 91久久久久久| 国产超碰| 裸体美女国产免费久久久网站| 婷婷五月天社区| 久久秀这里有精品| 久久妇| 97中文字幕一区| 亚洲福利影院一区久久| 成人三一级一片aaa| 精品人妻美妇91job| 午夜激情床戏激情| 破处bbq| 久久久97| 激情五月丁香五月| 人人超碰在线观看黄| 亚洲久久东京热一二三四五区视频| 蜜臀久久99精品久久久久久成人小说 | 91国产在线精品| 加勒比99999| 国模无码人体一区二区三| 激情视屏国产乱伦强奸| 天堂日本亚洲欧美| 少妇精品| 成年女人一区| 精品人妻一区二区三区日产乱码| 亚洲一本色码中文字幕| 久操高青| 少妇大屁屁| 亚洲视频1区| 美女刺激久久国产欧美| 91精品又粗又猛又爽| 黄片免费日韩| 中文字幕高清20页视频| 精品十八在线观看| 日韩精品 视频一区二区| 亚洲天堂东京热| 97超碰伊人| 一区二区三区探花在线观看| 色狠人在线99| 国产精品人妻无码久久久老鸭窝| 99热这里只有精| 91青青在线视频| 成人性爱av| 九九九久千久久激情蜜桃在线看| 国产精品视屏| 国产91美女高潮| 久99在线免费观看视频| 婷婷五月天激情网| 亚洲情色 欧美| 午夜福利视频在线一区| 欧美成人国产精品| 人妻aa| av一区二区三区四区五区久草臀| 秋霞免费无码视频日韩A片| 偷拍欧美激情| av一区二区三区不卡| 国产馆极品诱惑| 91春色| 九色97| 麻豆久久一区二区三区| www.操| 日韩免费一级性爱视频| 欧美日韩国产电影| 成人性爱美曰韩| 日本久久999| 亚洲一卡2卡3卡4卡乱码网站| 超碰97亚洲区| 高清无码国产亚洲| 国产午夜精品一区二区三区牛牛| 丁香六月天| 91成人18| 东北老女人的激情视频| 精品国产91av一区二区三区| 超碰伊人在线| 九九色精品| 91丨人妻丨国产丨丝袜| 精产国品一区二三产品| 秋霞蝌科网日本一区| wuyechaopeng| 亚洲天堂综合AV| 91人妻人人澡人人爽人人精品| 欧美色图偷拍另类| 一区二区三区免费岛国片| 女人18精品一区二区三区| 99热精品在线播放| 东京热视频网| 黄站在线免费观看| 91人妻丝袜无码| 九九干| 欧色网址| #NAME?| 色综合久| 八戒无码国产午夜福利| 国产91丝袜 在线播放| 亚洲第一页欧美| 人人操,操人人| 偷拍综合网| 亚洲男人的天堂网| 91狠| 久久久久国产一区二| 清纯唯美亚洲综合| 91少妇通奸网站| 水澄无码AV| 精品一区二区综合熟妇| 又大又大又大又粗爽高潮观看| 日韩丝袜高跟制服在线观看| 欧美亚洲日韩人妻在线观看| 奇米四色影视777久久久| 91亚洲人| 9久9久| 欧美白嫩女HD| 另类综合另类| 亚洲国产成人高清在线| 三级AV入口| 亚洲综合97| 精品成人久久久人人亚洲| 日韩国产十八禁| 亚洲色图91欧美日韩| 国产精品久久成人免费| 国产传媒午夜理伦精品| 天天综合网日韩| 天堂av最新电影网| 九九九九一级| 美女诱惑在线一区| 亚洲av热热色| 欧美三级一级| caorenqi shipin| 久久人人爽人人爽人人片Ⅴ| AAAAAAAAA黄片| 欧美人人曰人人操人人射射| 思思久热在线精品66| 久久精品28| 亚洲有薄码区久久在线一区| 国产99999久久精品| 欧美综合制服在线| 97se综合网| 亚洲成人一二三区| 偷拍 精品 另类 四区| 3571色综合一区二区二区| 国产精品成人无码av| 亚欧Av| 在线强奷到舒服的无码视频| xxx0国产在线播放| 国产精品久久久久中文字幕| 亚洲第一精品在线视频| 最好看的中文字幕在线2018| 在线岛| 岛国网址国产 | 97碰在线视频| 九九热超碰| 99热精品在线播放| 日韩免费人妻色情网站| 电影69乱码96| 狠狠搞 亚洲91| 午夜福利在线视频1000| 欧美青青视频| 亚洲精品久久一区二区三区蜜桃臀| 人妻黑丝袜电影| 久久久九九| 男女啊啊啊| 白丝一区| 先锋影音av先锋一区| 天堂а√在线最新版在线| 中文字幕一区二区在线日韩精品| 操逼操逼逼操操逼91| 999国产精品999| 这里只有精品视频在线| 大香蕉在线视频15| 日韩图区| 九七超碰人人乐| 日本一级特级毛片视频| 亚洲一区二区久久久久| 亚洲超碰在线| 97人人爱人人做人人乐| 韩日自拍| 国产色图乱伦| 久久久久久久久成人av解说| 男人夜色天堂ss| 亚洲精品骚逼| 亚洲少妇综合| 欧美熟妇成人一区二区| 无码自拍SM| 91大神电影天堂| 亚洲精品人伦一区二区| 免费视频一二三区| 亚洲最新中文字幕免费| 亚洲有薄码区日本系列中文字幕| 欧美国产一区二区三区麻豆传媒| 超碰97.com| 天天躁日日躁狠狠躁| 国产最新小视频在线播放下载| 亚洲第一无码播放立川理惠| 床上啊啊啊一区二区三区| 人妻在线大香蕉| 久久99国产精品| 国产又黄又爽又刺激久久久久久| 超碰在线91| 欧美久久人妻少妇一区二区| 爱爱动态60秒| 久久久久婷婷| 啊啊啊啊啊,啊啊啊啊好舒服,操我舒服啊啊啊| 91色伦综合| 青青草日韩无码| 男生女生啊啊啊啊| 五十路三区在线| 色乱二区| 亚洲欧美精品久| 91超碰在线| 99热9| 亚洲综合校园春色| 精品久久无码午夜福利| 天天狠| 亚洲玖玖爱| 人人艹亚洲| 大香蕉伊人一区在线观看| 国产精品伦理| 国产一级αv免费看片| 天天α片| 国产亚洲深夜激情| 青青操97| 91搡老女人老妇女老熟女歌词翻译| 被体育老师抱着c到高潮| 欧美国产一区二区三区麻豆传媒| 亚洲婷婷丁香在线| baisiav| 久久久久久久九九九九| 欧美在线视频99| JuliaAnnXXX888| 91一起操| 九九九九精品视频| 婷婷色色五月| 欧美日韩亚洲天堂| 91neishe| 狠狠操狠狠操操| 中文字幕二区日韩天堂 | 人人爱人人操人人性| 亚洲日韩东京热一区| 亚洲天堂一区二区久久| 免费成人在线熟妇网| 综合五月婷婷亚洲一区| 色天堂在线观看| 久久久久亚洲Aⅴ无码| 日韩人妻精品| 丁香六月啪| 亚洲狠| 亚州操操穴网| 999精品国产高清一区二区| 美女主播色欲91抠b在线播放| 国产乱色国产精品免费视| 无码视频一区二区| 中日韩熟女| 抽插一区二区视频| 日韩啪啪啪啪啪| 日韩成人性日韩成人性爱视频在线免费观看 | 久热色情精品| 日韩三A大片在线观看| 91强在线播放| 色色五月天激情| 蜜臀99久久精品久久久懂爱| 亚洲码和欧洲精品激情系列| 国产精品干干干| 4tube欧美女厕所| 久久国产精品一级二级三级| 日韩簧片免费看| 97超色| 无码又爽又硬又激情免费视频| 欧美色图综合| 青青操视频在线| 99热精品在线观看| 日韩高清黄片| 亚洲干B| 亚洲最大的黄色电影网站。| 欧美性爱三区二区| 97亚洲欧美| 亚洲成人妻日韩在线| 亚洲啪啪性视频| 国产一区二区成人av在线播放| 内射黑丝袜| 天美国产精品| 曰韩成人免费视频| 高清国产无码av| 啊啊啊 在线| 99啪啪视频| 性爱av在线免费观看| 欧美精品69性爱| 久久久天美| 欧中日成人免费影视| 国产精品无码AV网站| 国产在线综合网| 97超碰伊人| 韩国三级三级BD在线| 超碰久热| 欧美成人黄网色网站| 成人小说另类在线| 啊啊啊啊好多水| 日韩 欧美 国产 麻豆| 夜夜夜久久| 婷婷五月天成人网| 人人妻人人狠人人| 香蕉黄色一级视频| 国产捆绑一区| 欧美亚洲手机在线| 后入式999| 日韩操呦呦影院在线观看| 老女人爆菊| 国产一级片| 日韩不卡a级视频专区| 两女互慰AV高潮喷水在线观看| 国产精品乱码久久久| 黑人粗大V S日韩女优视频| 99抽插| 日韩三级网址| 91超碰人人| 欧日韩不卡视.频| 99色天堂| 99天堂网| 久久九九综合| 婷婷久月| 久久婷婷六月综合| 丁香五月自拍| 人人色人人操在线| 日本护士高潮| 亚洲午夜AV| 国产福利精品最新在线 | 97久久超碰日韩精品| 欧美精品,四区。五区| 亚州欧美总和| 亚洲涩图欧美| 欧美综合自拍亚洲综合图| 色臀aV| 91精品在线播放| 精品免费成人久久| 久99在线免费观看视频| 99rre在线精品99re8| 国产精品午夜福利| 99re28在线观看| 五月情色天| 一级二级在线观看| 国产无码精品无码| 中文人妻av高清一区| 在线无码网站| av片在线观看免费播放| 开心激情婷婷| 青青操97| 超碰97首页| 国产97色在线 | 亚洲| 国产路线专区| 少妇厨房愉情理伦片bd在线观看| 免费av在线播放二区| 国产91乱伦| 国产一区二区三区影片| 五月丁香综合| 区一二区日韩亚洲乱码av电影| 亚洲自拍一区夜夜操| 劲爆欧美人妖三区91| 精人妻一区二区三区| 91成人18| 强奸乱伦大香蕉| 丁香六月激情综合| 中美日韩毛片| 久久成人网站| 亚洲色天| 日韩国产成人自拍视频| 狠狠欧美| 欧美少妇高潮久久91| 夜夜嗨一区| 男插女青青影院| 探花一区在线| 江都AV在线| 综合网亚洲1| 天天看精品动漫视频一区| 亚洲系列第一页| 一区二区三区精品黑丝白丝酒店对鸡| 大香蕉伊人在线成人AV在线观看| 欧美精品不卡一二三四在线91| 精品无码久久久久久久久果冻糖心| 精品成人亚洲午夜电影| 天天天天干| 97频视在线| 97欧美精品| 国产 v乱码一区二| 97色色国产视频| henhen91| 亚洲成a人片在线观看中文!!!| 免费夜夜爱黄色视频毛片| 97精品久久久久中文字幕| 欧美爱爱97| 久久 国产精品 一区| 怡春苑东京热| 无码不卡亚洲成?人片| 久久精品性| 熟妇人妻一区二区三在线| 91精品91久久久久77777俄罗斯老妇姓x| 爽极品影院| 久热久一区二区三区| 午夜福利合集| 亚洲97久久精品亚洲| 欧美狠狠操| 亚欧色图在线激情| 精品久久99| 久久久国产护士丝袜美腿一| av在线播放国产一区| 野狼激情网| 99热这里只有精品18| 中文字幕av乱伦| 99热8| 2019天天干天天操| 草伊人高潮喷水超碰| 精品一区二区三区免费古装毛片香港三级日本三级人妇 | 亚洲人人操| 天天性射网| 亚洲一区二区三区四区视频| 国产精品亚洲日韩骚欢乐谷最新地址发布页huanieguty性屋娱乐妖精视频 | 日韩精品午夜操呦呦不卡影院| 国产 日韩 欧美 中文 另类,国产 欧美 另类 制服 变态,高清 日韩 欧美 中文,高 | 欧美黄色手机在线观看| 色蜜AV| 一区二区三区四区理论片| 天天天天天干夜夜夜夜夜操| 欧美丝袜美女电影一二三四区| 蜜乳Av成人片网站| 亚洲Av噜噜一区二区三区妖精| 亚洲伊人久久综合97| 欧美亚综合色图| 欧美人黑A片无码免视费| 69精品少妇一区二区三区蜜桃| 日韩在线电影| 国产高清1234区| 国产成人欧美精品在线| 亚洲免费精品一区| 91性高朝久久久久久久久| 黄网站黄视频网站进入口| 黄色片A级一区二区三区| 伊人久久大香线综合无码| 午夜操逼不卡| 欧美在线综合| 97色色婷婷| 久久久无码视频| 亚洲av总站| 黄色激情电影在线观看| 少妇丝袜在线观看AV| 欧美成人黄网色网站| 亚洲猛交| 中文字幕91综合| 岛国片在线播放| 国模91| www.婷婷| 中字幕人妻一区二区三区| 神马久久久久久久久久久久| 亚洲暴力强奸AV| 亚洲丝袜二区在线| 久操高青| 色成人Www精品永久观看| 亚洲天堂少妇| 伊人影院在线理论播放| 免费又黄又裸乳的视频| 啊啊啊 在线| 麻豆天美国美国产| 国产91啪| 亚洲精品欧洲色| 嗯嗯,好大,好爽,好骚| 欧美性巨大╳╳╳╳╳高跟鞋| 久久伊人东京热| 久久超碰亚洲人| 欧美激情中文字幕另类小说| 2017天天拍大香蕉| 91天射| 国产一区二区三区中文字幕| 国产精品一区二区亚洲人成毛片| 91精品国| 91欧美成人色站| 人人看人人摸人人色| 黄片视频观看| 久久久免费视频18| 在线视频一区二区传媒| 大香蕉乱伦视频网| 一区二区三区在线美女| 麻豆av一区二区| 大香蕉综合在线| 久久国产99精品72福利| 在线无码操| 欧州一区二区三区四区| 国产一区二区在线看| 久久精9| 欧美一级三级| 日韩丝袜二区| 国产AV色黄看到爽| 91老熟女| 91n处女在线观看| 日韩精品国模| 亚洲成人精品久久久| 狂操嫩妻视频一区二区三区| 日韩国产在线观看av| 日本人妻丰满熟妇久久久久久| 欧美激情一| 九九国产热| 亚洲一区二区三区麻豆传媒| 亚洲精品 大香蕉| 中文字幕在线观看二区三区| 亚洲成人性爱网站在线播放| 校园春色综合网| 精品对白久久不卡| 99草精| 亚洲综合 欧美| 91激情网| 1二区9| 青久操| 欧中日成人免费影视| 中文无码一二三区| 91粉芽高清在线一区二区| 国产一区二区三区影片| a级成人毛片免费视频高清| 老熟女搡BBBB搡BBBB视频| 国产精品爆乳懂色蜜乳| 日韩精品人妻| 国产精品操| 78超碰| 麻豆成人影音在线| 欧美色性情| 91岛国动作片| 综合网 欧美| 97资源久久| 亚洲人妻久久| 男人的天堂 在线一区| 免费视频97| 97干97色| 亚洲无码偷拍| 久久精品午夜国产亚洲AV无码| 天天上日日上日韩精品| 日韩成人性日韩成人性爱视频在线免费观看| 天天射夜夜骑| 久久一二三四| 少妇厨房愉情理伦片bd在线观看| 性爱网站一区二区| 无码外流操逼视频| 黄页视频网站野外| 国产18精品亚洲精品| 凹凸视频特色日本特黄| 国产原创自拍| 福利偷拍视频-中文字幕2019国语完整视频大全-S91AV | 无码不卡八戒| 芊芊操逼视频无码| 91 亚洲 欧美 日韩 国产 综合| 中文自拍欧美影视| 欧美色五月| 18精品一区| 国产亚洲色婷婷99精品91| 久久精品人妻一区二区| 欧美偷| av网站免费看| 99re公开精品免费视频| 亚洲 欧美日韩 另类| 99re在线观看| 99re8超碰| 91女优在线观看 | 欧美成人性爱视频在线播放| 国产精品干干干| 曰韩无码777| 综合国产97| 成人片视频| 少妇三p| 在线毛片片免费观看| 操逼视频免费日韩无码| 农村妇女一级二级三级视频| 日本五十路在线| 老女人老91妇女老热女| 丝袜美腿丝袜| 边做饭边操逼逼| 日本五十路熟女一区二区| 亚洲少妇喷视频看| 欧美性爱一区二区三区四区| 高潮9999外国| 可以免费看黄片的视频| 一级啊性爱在线视频| 超碰97爽| 国产91丝袜在线播放蜜月| 99热| 人人透人人操| 人妻精品一区二区全免费| 欧美成人贴图| 天天操夜夜操狠很操| 99热官网| 欧美一品道| 天堂69亚洲精品中文字| 超碰99在线观看| 夜草欧美| 国产一级内射高清视频| 国产熟女乱论| 黑人中出21连凳花野真衣| 中国少妇啪啪视频| 约操熟妇| 磁力99AV| 国产精品高潮久久久无码| 国模少妇一区二区三区| 欧美色日本| 欧洲性爱无码区| 色色操| 加勒比色综合| 少妇一区二区三区高速| http://qxhbdz.com| 日韩本不卡视频在线观看| 日韩亚洲中文字幕在线| 99re在线观看| 夜夜骑夜夜操| 成人婷婷丁香| 国内外激情在线| 欧美精品久久久久久久久88| 91久久堂| 国产av激情无码久久天堂| 9/A片| 色欧美亚洲| 正在播放:深夜激情大战,自带黑丝袜全力输出骚穴 | 熟妇视频一区二区三区在线观看| 校园春色第一页| 色播综合| 综合网亚洲在线| 日本三级R| 人人摸人人舔一区二区| 91人妻中文| 骚人妻少妇视频| 乳欲人妻办公室奶水| 91国产美女丝袜足交精品视频| 八戒午夜福利理论片| 日韩三级在线观看mp4| 成人26uuu| 情色五月天久久久| 欧美成人A√在线一区二区| 人妻插插人妻人| 日本韩国国产精品一区| 亚洲棕合电彰| 亚洲 日本 国产 综合| 操一区| 国产一级操B视频| 欧洲亚洲综合| 性爱av网站| 韩日欧亚a级| 欧美成人都市人妻| 91春色| 亚洲蜜臀懂色| 中文字幕奈奈美被公侵犯| 好吊爽好吊爽在线视频,中文字幕精品一区二区日本,国产良妇出轨视频在线观看, | 岛国人妻少妇av在线观看| 国产亚洲精品久久久久小| 蜜臀AV成人精品蜜臀| 2019天天干天天操| 福利天天都操| 欧美国产日韩清纯唯美| 97操| 91/欧美| 亚洲免费人妻在| 热99re69精品8在线播放| 亚洲情色五月天| 99国产在线 精品 视频| 9997se| 欧美不卡在线美女| 久久久久久久九九九九九九| 日本天堂网| 国内精品久久国产,www香蕉久久五月丁香,亚洲欧美日韩精品永久在线,日本精品一 | 国产激情久久久| 色激情综合网站| 91骚妇| 精品婷婷| 欧洲特黄毛片免费看欧洲毛片| 欧美一二在线| 欧美一级做a爰片免费视频| 人妻铁牛TV| 男人的天堂日本东京热| 五月丁香影院| 综合国产影视三级| 一本大道久| 第四色色综合91| 亚洲Av无码成人精品国产| 啊啊啊啊啊啊在线观看| 天天激色| 大香蕉AV丝袜| 强奸乱伦动态污图免费| 欧美色女人| 色综合1991| 欧美日韩理论一区| 一块操欧美| 天天日天天搞天天干| 99999国产| 亚洲无限观看| 蜜臀精品1区2区| 人成午夜免费大片| 情趣丝袜无码操逼视频| 5252色欧美在线男人的天堂| 精品国产99| 欧美亚洲日韩人妻在线观看| 人人艹亚洲| 亚洲伊人成综合成人网| 欧美桃色网| 狠综合网| 91亚洲不卡一区| 九九香蕉网| 国产精品无套内谢| 国产中出内射一区二区| 青草伊人网| 国产精品国产| 久久久久久久久九九久孕交| www.狠狠操| 色官网在线| 日韩欧美中文日韩欧美色| A 天堂| 色欧洲| 99久在线精品99re8蜜桃| 中文字幕欧美日本乱码一线二线| 久久久久久九九九九-美女久久久久久久-成人AV | 偷拍 精品 另类 四区| 久久色情| 亚洲欧美日韩夜夜| 岛国大片在线观看网站入口| 一区AV| 婷婷丁香激情| 久久久久久九九九九| 天天欲望网| 97在线/亚洲| 夫妻AV网站| 九九超碰综合网| 日韩精品影视| 国产精品午夜福利视频| 一本久久精品中文字| 亚洲中文电影| 欧美综合在线91| 97色视频在线| 日本 免费 一区二区三区 久久香蕉| 久久久久久久久久久久久久久性生活视频| 九九色婷婷| 99精品在线| 加勒比大香蕉视频在线| 久热这里| 淫淫总合网| 禁止观看美女黄| 中文字幕在线观看网页| 在线综合 亚洲 欧美中文字幕 | 午夜超碰| 亚洲精品久久久久毛片A片拉屎 | 曰本91情色| 男女打扑克高清网站| 欧美制服另类丝袜| 手机不卡视频不卡在线一二三区| 毛片久久| 日韩无码嘿咻黑热久| 欧美日不卡| www.欧精品| 欧美久久毛片基地| 国产亚洲色婷婷99精品91| 国产精品丝袜久久亚洲不卡| 91女优在线观看 | 天天日天天干天天摸天天操|