入門昇騰AI媒體預處理技術

      網(wǎng)友投稿 943 2022-05-30

      CANN媒體數(shù)據(jù)處理

      1.為什么我們要學習CANN的媒體數(shù)據(jù)處理

      當然是速度快呀

      媒體數(shù)據(jù)處理在不同的應用里面有不同的含義,今天我們說的媒體數(shù)據(jù)處理主要是指開發(fā)AI應用,為模型制造合適的數(shù)據(jù),和模型推理完后后處理的一系列操作,一般包括圖片的解碼,編碼,縮放,裁剪,視頻的解碼編碼等等操作。

      但是對深度學習了解一點的朋友可能都知道我們一般會用opencv等加速數(shù)據(jù)的處理,既然有解決辦法了,再學習一種新的,有點多余吧?

      NO!NO!NO!

      我們都了解GPU可以加速神經(jīng)網(wǎng)絡模型的訓練和推理,但是CPU也行啊,但是你了解他們之間的速度差異嗎?二者效率相差可能達到幾十倍甚至是上百倍,并不是CPU太遜了,也不是GPU太強了,這兩種都是計算機的硬件都有著不同的特點。

      CPU的可以形象的理解為有25%的ALU(運算單元)、有25%的Control(控制單元)、50%的Cache(緩存單元)

      GPU可以形象的理解為90%的ALU(運算單元),5%的Control(控制單元)、5%的Cache(緩存單元)

      二者天然就有非常大的差異,然而各種數(shù)據(jù)處理運算都要有ALU完成,但是CPU為了完成一系列復雜的控制功能,運算單元的數(shù)量相比于GPU其實很少,所以面對高密度的計算任務時GPU就有天然的優(yōu)勢。這就是硬件優(yōu)勢。

      然而我們的主角昇騰AI處理器是NPU,是一種相比于GPU更加適合AI運算的硬件,通過NPU的加速又可以實現(xiàn)數(shù)量級的效率提升。因此數(shù)據(jù)處理的操作在NPU上進行專門的加速,就可以達到數(shù)倍提升效率的成果。當需要處理的數(shù)據(jù)比較多的時候,優(yōu)勢就會進一步體現(xiàn)。

      2.在專門的芯片上進行媒體數(shù)據(jù)處理這么厲害,我要怎么學習呢?

      別急一步一來

      第一式,摸清敵情

      入門昇騰AI媒體預處理技術

      媒體數(shù)據(jù)處理是什么

      媒體數(shù)據(jù)都可以應用在哪些方面

      媒體數(shù)據(jù)處理在接口調(diào)用流程中的位置

      第二式,逐個擊破

      在計算機視覺領域處理最多的應該也就是圖片和視頻了,

      所以,我們先學習JPEG圖片的解碼和編碼,

      溫馨提示視頻中講述的是各種數(shù)據(jù)處理的集合哦,可以按需跳躍觀看

      媒體數(shù)據(jù)處理

      實驗體驗

      誒嘿嘿,代碼來嘍!!

      但是,寫代碼之前我們最好要知道我們整個程序的流程,那么它來嘍

      首先就是創(chuàng)建數(shù)據(jù)處理的通道,你可以把它理解為一個專為處理媒體數(shù)據(jù)的生產(chǎn)線,在這個生產(chǎn)線上會對媒體數(shù)據(jù)(圖片,視頻)進行加工

      //1.創(chuàng)建和銷毀圖片數(shù)據(jù)處理的通道。 dvppChannelDesc_ = acldvppCreateChannelDesc(); aclError ret = acldvppCreateChannel(dvppChannelDesc_); acldvppDestroyChannel(dvppChannelDesc_);

      然后要為生產(chǎn)線準備原材料,也就是圖片或者視頻的源數(shù)據(jù)(把數(shù)據(jù)加載到顯存里面)

      //調(diào)用aclrtGetRunMode接口獲取軟件棧的運行模式,如果調(diào)用aclrtGetRunMode接口獲取軟件棧的運行模式為ACL_HOST,則需要通過aclrtMemcpy接口將輸入圖片數(shù)據(jù)傳輸?shù)紻evice,數(shù)據(jù)傳輸完成后,需及時釋放內(nèi)存;否則直接申請并使用Device的內(nèi)存 aclrtRunMode runMode; ret = aclrtGetRunMode(&runMode); if(runMode == ACL_HOST){ //申請Host內(nèi)存inputHostBuff,并將輸入圖片讀入該地址,inDevBufferSize為讀入圖片大小 void* inputHostBuff = nullptr; inputHostBuff = malloc(inDevBufferSize); //將輸入圖片讀入內(nèi)存中,該自定義函數(shù)ReadPicFile由用戶實現(xiàn) ReadPicFile(picName, inputHostBuff, inDevBufferSize); //申請Device內(nèi)存inDevBuffer_ aclRet = acldvppMalloc(&inDevBuffer_, inDevBufferSize); //通過aclrtMemcpy接口將輸入圖片數(shù)據(jù)傳輸?shù)紻evice aclRet = aclrtMemcpy(inDevBuffer_, inDevBufferSize, inputHostBuff, inDevBufferSize, ACL_MEMCPY_HOST_TO_DEVICE); } else { //申請Device輸入內(nèi)存inDevBuffer_ ret = acldvppMalloc(&inDevBuffer_, inBufferSize); //將輸入圖片讀入內(nèi)存中,該自定義函數(shù)ReadPicFile由用戶實現(xiàn) ReadPicFile(picName, inDevBuffer_, inBufferSize); }

      然后要為生產(chǎn)過程設置參數(shù),設置圖片的描述信息,這個你可以類比于我們需要告訴生產(chǎn)線,這批原材料的相關信息,家庭住址,高矮胖瘦,什么成分

      //創(chuàng)建解碼輸出圖片的描述信息,設置各屬性值 //decodeOutputDesc是acldvppPicDesc類型 decodeOutputDesc_ = acldvppCreatePicDesc(); //數(shù)據(jù)描述,這個為了告訴生產(chǎn)線要去哪里找數(shù)據(jù),其實就是類似于數(shù)據(jù)的首地址 acldvppSetPicDescData(decodeOutputDesc_, decodeOutDevBuffer_); //告訴生產(chǎn)線這張圖片占用多少內(nèi)存,以防一會取數(shù)據(jù)取多了 acldvppSetPicDescSize(decodeOutputDesc_, decodeOutBufferSize); //告訴生產(chǎn)線圖片是什么格式的 acldvppSetPicDescFormat(decodeOutputDesc_, PIXEL_FORMAT_YUV_SEMIPLANAR_420); //告訴生產(chǎn)線圖片寬多少 acldvppSetPicDescWidth(decodeOutputDesc_, inputWidth_); //告訴生產(chǎn)線圖片高多少 acldvppSetPicDescHeight(decodeOutputDesc_, inputHeight_); //告訴生產(chǎn)線數(shù)據(jù)對齊后的寬是多少 acldvppSetPicDescWidthStride(decodeOutputDesc_, decodeOutWidthStride); 告訴生產(chǎn)線對齊后的高是多少 acldvppSetPicDescHeightStride(decodeOutputDesc_, decodeOutHeightStride);

      然后準備工作完成,開始加工了

      //執(zhí)行異步解碼,再調(diào)用aclrtSynchronizeStream接口阻塞程序運行,直到指定Stream中的所有任務都完成 ret = acldvppJpegDecodeAsync(dvppChannelDesc_, inDevBuffer_, inDevBufferSize, decodeOutputDesc_, stream_); ret = aclrtSynchronizeStream(stream_);

      加工完了,該打包裝箱了,貼封條了(其實就是把數(shù)據(jù)從顯存拷貝回內(nèi)存里面,為后面保存做準備)

      if(runMode == ACL_HOST) { //該模式下,由于處理結(jié)果在Device側(cè),因此需要調(diào)用內(nèi)存復制接口傳輸結(jié)果數(shù)據(jù)后,再釋放Device側(cè)內(nèi)存 //申請Host內(nèi)存vpcOutHostBuffer void* vpcOutHostBuffer = nullptr; vpcOutHostBuffer = malloc(decodeOutBufferSize); //通過aclrtMemcpy接口將Device的處理結(jié)果數(shù)據(jù)傳輸?shù)紿ost aclRet = aclrtMemcpy(vpcOutHostBuffer, decodeOutBufferSize, decodeOutDevBuffer_, decodeOutBufferSize, ACL_MEMCPY_DEVICE_TO_HOST); //釋放掉輸入輸出的device內(nèi)存 (void)acldvppFree(inDevBuffer_); (void)acldvppFree(decodeOutDevBuffer_); //數(shù)據(jù)使用完成后,釋放內(nèi)存 free(vpcOutHostBuffer); } else { //此時運行在device側(cè),處理結(jié)果也在Device側(cè),可以根據(jù)需要操作處理結(jié)果后,釋放Device側(cè)內(nèi)存 (void)acldvppFree(inDevBuffer_); (void)acldvppFree(decodeOutDevBuffer_); }

      解碼結(jié)束后,釋放資源,包括解碼輸出圖片的描述信息、解碼輸出內(nèi)存、通道描述信息、通道等(干完活你得把場地收拾好)

      acldvppDestroyPicDesc(decodeOutputDesc_); acldvppDestroyChannel(dvppChannelDesc_); (void)acldvppDestroyChannelDesc(dvppChannelDesc_);

      搞定了

      解碼完成了,我們想對圖片進行一個縮放,該咋辦呢??

      同樣先來一個流程圖

      其實還是那個套路

      先準備生產(chǎn)線

      // 創(chuàng)建圖片數(shù)據(jù)處理通道時的通道描述信息,dvppChannelDesc_是acldvppChannelDesc類型 dvppChannelDesc_ = acldvppCreateChannelDesc();

      創(chuàng)建圖片縮放配置數(shù)據(jù)、指定縮放算法,圖片縮放后會成什么鳥樣子和采用什么算法有很大差異,中國廚子和外國廚子做出的菜能一個味嗎??

      //resizeConfig_是acldvppResizeConfig類型 acldvppResizeConfig *resizeConfig_ = acldvppCreateResizeConfig(); aclError ret = acldvppSetResizeConfigInterpolation(resizeConfig_, 0);

      準備原材料(將數(shù)據(jù)讀到內(nèi)存,再拷貝到顯存)

      //申請輸入內(nèi)存(區(qū)分運行狀態(tài)) //調(diào)用aclrtGetRunMode接口獲取軟件棧的運行模式,如果調(diào)用aclrtGetRunMode接口獲取軟件棧的運行模式為ACL_HOST,則需要通過aclrtMemcpy接口將輸入圖片數(shù)據(jù)傳輸?shù)紻evice,數(shù)據(jù)傳輸完成后,需及時釋放內(nèi)存;否則直接申請并使用Device的內(nèi)存 aclrtRunMode runMode; ret = aclrtGetRunMode(&runMode); //inputPicWidth、inputPicHeight分別表示圖片的對齊后寬、對齊后高,此處以YUV420SP格式的圖片為例 uint32_t resizeInBufferSize = inputPicWidth * inputPicHeight * 3 / 2; if(runMode == ACL_HOST) { //申請Host內(nèi)存vpcInHostBuffer void* vpcInHostBuffer = nullptr; vpcInHostBuffer = malloc(resizeInBufferSize); //將輸入圖片讀入內(nèi)存中,該自定義函數(shù)ReadPicFile由用戶實現(xiàn) ReadPicFile(picName, vpcInHostBuffer, resizeInBufferSize); //申請Device內(nèi)存resizeInDevBuffer_ aclRet = acldvppMalloc(&resizeInDevBuffer_, resizeInBufferSize); //通過aclrtMemcpy接口將輸入圖片數(shù)據(jù)傳輸?shù)紻evice aclRet = aclrtMemcpy(resizeInDevBuffer_, resizeInBufferSize, vpcInHostBuffer, resizeInBufferSize, ACL_MEMCPY_HOST_TO_DEVICE); //數(shù)據(jù)傳輸完成后,及時釋放內(nèi)存 free(vpcInHostBuffer); } else { //申請Device輸入內(nèi)存resizeInDevBuffer_ ret = acldvppMalloc(&resizeInDevBuffer_, resizeInBufferSize); //將輸入圖片讀入內(nèi)存中,該自定義函數(shù)ReadPicFile由用戶實現(xiàn) ReadPicFile(picName, resizeInDevBuffer_, resizeInBufferSize); }

      這里有個點要注意,圖片縮放以后占用的空間必然會發(fā)生變化,因此我們需要一個新的容器才能存下,正所謂鯤之大,一鍋燉不下

      //申請縮放輸出內(nèi)存resizeOutBufferDev_,內(nèi)存大小resizeOutBufferSize_根據(jù)計算公式得出 //outputPicWidth、outputPicHeight分別表示圖片的對齊后寬、對齊后高,此處以YUV420SP格式的圖片為例 uint32_t resizeOutBufferSize_ = outputPicWidth * outputPicHeight * 3 / 2; ret = acldvppMalloc(&resizeOutBufferDev_, resizeOutBufferSize_)

      然后要告訴生產(chǎn)線,做之前材料是啥樣子,完成后要是什么樣子

      //創(chuàng)建縮放輸入圖片的描述信息,并設置各屬性值 //resizeInputDesc_是acldvppPicDesc類型 resizeInputDesc_ = acldvppCreatePicDesc(); //告訴昇騰處理器去哪個貨架找數(shù)據(jù) acldvppSetPicDescData(resizeInputDesc_, resizeInDevBuffer_); //拿多少數(shù)據(jù) acldvppSetPicDescSize(resizeInputDesc_, resizeInBufferSize); //輸入的圖片是哪片山頭的 acldvppSetPicDescFormat(resizeInputDesc_, PIXEL_FORMAT_YUV_SEMIPLANAR_420); //輸入圖片寬度 acldvppSetPicDescWidth(resizeInputDesc_, inputWidth_); //輸入圖片的高度 acldvppSetPicDescHeight(resizeInputDesc_, inputHeight_); //對齊后的寬度 acldvppSetPicDescWidthStride(resizeInputDesc_, inputWidthStride); //對齊后的高度 acldvppSetPicDescHeightStride(resizeInputDesc_, inputHeightStride); //創(chuàng)建縮放輸出圖片的描述信息,并設置各屬性值 //如果縮放的輸出圖片作為模型推理的輸入,則輸出圖片的寬高要與模型要求的寬高保持一致 //resizeOutputDesc_是acldvppPicDesc類型 resizeOutputDesc_ = acldvppCreatePicDesc(); //處理完的數(shù)據(jù)放哪里,包裝箱放哪里 acldvppSetPicDescData(resizeOutputDesc_, resizeOutBufferDev_); //這個產(chǎn)品多大,占多大地方 acldvppSetPicDescSize(resizeOutputDesc_, resizeOutBufferSize_); //哪個山頭的 acldvppSetPicDescFormat(resizeOutputDesc_, PIXEL_FORMAT_YUV_SEMIPLANAR_420); //想要縮放到的寬度 acldvppSetPicDescWidth(resizeOutputDesc_, resizeOutputWidth_); //想要縮放的高度 acldvppSetPicDescHeight(resizeOutputDesc_, resizeOutputHeight_); //對齊后的寬度 acldvppSetPicDescWidthStride(resizeOutputDesc_, resizeOutputWidthStride); //對齊后的高度 acldvppSetPicDescHeightStride(resizeOutputDesc_, resizeOutputHeightStride);

      開始縮放吧

      //執(zhí)行異步縮放,再調(diào)用aclrtSynchronizeStream接口阻塞程序運行,直到指定Stream中的所有任務都完成 ret = acldvppVpcResizeAsync(dvppChannelDesc_, resizeInputDesc_, resizeOutputDesc_, resizeConfig_, stream_); ret = aclrtSynchronizeStream(stream_);

      縮放結(jié)束后,釋放資源,包括縮放輸入/輸出圖片的描述信息、縮放輸入/輸出內(nèi)存

      acldvppDestroyPicDesc(resizeInputDesc_); acldvppDestroyPicDesc(resizeOutputDesc_); if(runMode == ACL_HOST) { //該模式下,由于處理結(jié)果在Device側(cè),因此需要調(diào)用內(nèi)存復制接口傳輸結(jié)果數(shù)據(jù)后,再釋放Device側(cè)內(nèi)存 //申請Host內(nèi)存vpcOutHostBuffer void* vpcOutHostBuffer = nullptr; vpcOutHostBuffer = malloc(resizeOutBufferSize_); //通過aclrtMemcpy接口將Device的處理結(jié)果數(shù)據(jù)傳輸?shù)紿ost aclRet = aclrtMemcpy(vpcOutHostBuffer, resizeOutBufferSize_, resizeOutBufferDev_, resizeOutBufferSize_, ACL_MEMCPY_DEVICE_TO_HOST); //釋放掉輸入輸出的device內(nèi)存 (void)acldvppFree(resizeInDevBuffer_); (void)acldvppFree(resizeOutBufferDev_); //數(shù)據(jù)使用完成后,釋放內(nèi)存 free(vpcOutHostBuffer); } else { //此時運行在device側(cè),處理結(jié)果也在Device側(cè),可以根據(jù)需要操作處理結(jié)果后,釋放Device側(cè)內(nèi)存 (void)acldvppFree(resizeInDevBuffer_); (void)acldvppFree(resizeOutBufferDev_); }

      嘿嘿,又完成了!

      最后一個,解碼視頻流

      流程圖給爺上

      這個視頻解碼與圖片有點不一樣,我們都了解視頻就是一堆圖像連續(xù)播放.一秒鐘可能有幾十幀的圖像,所以我們就不可以像,一條流水線一樣從前到后完全做完在做下一個,要把解碼完成的后處理動作轉(zhuǎn)移到另一條生產(chǎn)線上

      創(chuàng)建回調(diào)函數(shù),處理解碼視頻以外的所有事情

      //3.創(chuàng)建回調(diào)函數(shù),這個函數(shù)就是另一條生產(chǎn)線上做的事情,除了不負責解碼,啥都做 void callback(acldvppStreamDesc *input, acldvppPicDesc *output, void *userdata) { static int count = 1; if (output != nullptr) { //獲取VDEC解碼的輸出內(nèi)存,調(diào)用自定義函數(shù)WriteToFile將輸出內(nèi)存中的數(shù)據(jù)寫入文件后,再調(diào)用acldvppFree接口釋放輸出內(nèi)存 void *vdecOutBufferDev = acldvppGetPicDescData(output); if (vdecOutBufferDev != nullptr) { // 0: vdec success; others, vdec failed //retCode為0表示解碼成功,為1表示解碼失敗。如果解碼失敗,需要根據(jù)日志中的返回碼判斷具體的問題,返回碼請參見返回碼說明。 int retCode = acldvppGetPicDescRetCode(output); if (retCode == 0) { // process task: write file uint32_t size = acldvppGetPicDescSize(output); std::string fileNameSave = "outdir/image" + std::to_string(count); // vdec輸出結(jié)果在device側(cè),在WriteToFile方法中進行下述處理 if (!Utils::WriteToFile(fileNameSave.c_str(), vdecOutBufferDev, size)) { ERROR_LOG("write file failed."); } } else { ERROR_LOG("vdec decode frame failed."); } // free output vdecOutBufferDev aclError ret = acldvppFree(vdecOutBufferDev); } // 釋放acldvppPicDesc類型的數(shù)據(jù),表示解碼后輸出圖片描述數(shù)據(jù) aclError ret = acldvppDestroyPicDesc(output); } // free input vdecInBufferDev and destroy stream desc if (input != nullptr) { void *vdecInBufferDev = acldvppGetStreamDescData(input); if (vdecInBufferDev != nullptr) { aclError ret = acldvppFree(vdecInBufferDev); } // 釋放acldvppStreamDesc類型的數(shù)據(jù),表示解碼的輸入碼流描述數(shù)據(jù) aclError ret = acldvppDestroyStreamDesc(input); } INFO_LOG("success to callback %d.", count); count++; }

      準備數(shù)據(jù),把數(shù)據(jù)的準備好,各項信息都標好

      //4.創(chuàng)建視頻碼流處理通道時的通道描述信息,設置視頻處理通道描述信息的屬性,其中線程、callback回調(diào)函數(shù)需要用戶提前創(chuàng)建。 //vdecChannelDesc_是aclvdecChannelDesc類型 vdecChannelDesc_ = aclvdecCreateChannelDesc(); //創(chuàng)建一個標致這條生產(chǎn)線的標志 ret = aclvdecSetChannelDescChannelId(vdecChannelDesc_, 10); //另一條生產(chǎn)線的位置 ret = aclvdecSetChannelDescThreadId(vdecChannelDesc_, threadId_); //另一條生產(chǎn)線要干的工作 ret = aclvdecSetChannelDescCallback(vdecChannelDesc_, callback); //示例中使用的是H265_MAIN_LEVEL視頻編碼協(xié)議,視頻的編碼 ret = aclvdecSetChannelDescEnType(vdecChannelDesc_, static_cast(enType_)); //示例中使用的是PIXEL_FORMAT_YVU_SEMIPLANAR_420,解碼后的圖片的編碼 ret = aclvdecSetChannelDescOutPicFormat(vdecChannelDesc_, static_cast(format_)); //5.創(chuàng)建視頻碼流處理的通道 ret = aclvdecCreateChannel(vdecChannelDesc_);

      //調(diào)用aclrtGetRunMode接口獲取軟件棧的運行模式,如果調(diào)用aclrtGetRunMode接口獲取軟件棧的運行模式為ACL_HOST,則需要通過aclrtMemcpy接口將輸入圖片數(shù)據(jù)傳輸?shù)紻evice,數(shù)據(jù)傳輸完成后,需及時釋放內(nèi)存;否則直接申請并使用Device的內(nèi)存 aclrtRunMode runMode; ret = aclrtGetRunMode(&runMode); if(runMode == ACL_HOST){ //申請Host內(nèi)存inputHostBuff void* inputHostBuff= nullptr; //inBufferSize_為輸入碼流大小 inputHostBuff= malloc(inBufferSize_); //將輸入圖片讀入內(nèi)存中,該自定義函數(shù)ReadPicFile由用戶實現(xiàn) ReadPicFile(picName, inputHostBuff, inBufferSize_); //申請Device內(nèi)存inBufferDev_ aclRet = acldvppMalloc(&inBufferDev_, inBufferSize_); //通過aclrtMemcpy接口將輸入圖片數(shù)據(jù)傳輸?shù)紻evice aclRet = aclrtMemcpy(inBufferDev_, inBufferSize_, inputHostBuff, inBufferSize_, ACL_MEMCPY_HOST_TO_DEVICE); //數(shù)據(jù)傳輸完成后,及時釋放內(nèi)存 free(inputHostBuff); } else { //申請Device輸入內(nèi)存dataDev, StreamBufferSize為輸入碼流大小 ret = acldvppMalloc(&inBufferDev_, inBufferSize_); //將輸入圖片讀入內(nèi)存中,該自定義函數(shù)ReadPicFile由用戶實現(xiàn) ReadPicFile(picName, inBufferDev_, inBufferSize_); }

      標志出來輸入的視頻的個人信息,以及輸出的圖片的個人信息

      //7.1 創(chuàng)建輸入視頻碼流描述信息,設置碼流信息的屬性 streamInputDesc_ = acldvppCreateStreamDesc(); //inBufferDev_表示Device存放輸入視頻數(shù)據(jù)的內(nèi)存,inBufferSize_表示內(nèi)存大小 ret = acldvppSetStreamDescData(streamInputDesc_, inBufferDev_); ret = acldvppSetStreamDescSize(streamInputDesc_, inBufferSize_); //7.2 申請Device內(nèi)存picOutBufferDev_,用于存放VDEC解碼后的輸出數(shù)據(jù) ret = acldvppMalloc(&picOutBufferDev_, size); //7.3 創(chuàng)建輸出圖片描述信息,設置圖片描述信息的屬性 //picOutputDesc_是acldvppPicDesc類型 picOutputDesc_ = acldvppCreatePicDesc(); ret = acldvppSetPicDescData(picOutputDesc_, picOutBufferDev_); ret = acldvppSetPicDescSize(picOutputDesc_, size); ret = acldvppSetPicDescFormat(picOutputDesc_, static_cast(format_));

      開始解碼

      //7.4 執(zhí)行視頻碼流解碼,解碼每幀數(shù)據(jù)后,系統(tǒng)自動調(diào)用callback回調(diào)函數(shù)將解碼后的數(shù)據(jù)寫入文件,再及時釋放相關資源 ret = aclvdecSendFrame(vdecChannelDesc_, streamInputDesc_, picOutputDesc_, nullptr, nullptr);

      清理一下場地

      //8.釋放圖片處理通道、圖片描述信息 ret = aclvdecDestroyChannel(vdecChannelDesc_); aclvdecDestroyChannelDesc(vdecChannelDesc_);

      至此,圖片解碼,縮放,視頻解碼已經(jīng)全部完成

      本文的介紹,還有好多函數(shù)的細節(jié)未曾解釋清楚,歡迎各位查看官方的文檔,進行系統(tǒng)化的學習,讓我們一起建設國產(chǎn)軟件的生態(tài)

      昇騰文檔

      云端實踐 媒體處理 昇騰 機器學習

      版權聲明:本文內(nèi)容由網(wǎng)絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實的內(nèi)容,請聯(lián)系我們jiasou666@gmail.com 處理,核實后本網(wǎng)站將在24小時內(nèi)刪除侵權內(nèi)容。

      上一篇:云市場11月新品一覽
      下一篇:Nature評選改變科學的10個計算機代碼,arXiv、AlexNet等上榜
      相關文章
      亚洲最大AV网站在线观看| 综合亚洲伊人午夜网| 国产av无码专区亚洲国产精品| 中文字幕亚洲男人的天堂网络 | 亚洲av无码偷拍在线观看| 亚洲一区二区三区丝袜| 99热亚洲色精品国产88| 亚洲午夜国产精品| 亚洲一级片在线观看| 精品亚洲国产成人| 一区二区亚洲精品精华液| 久久国产亚洲精品| 亚洲国产精品99久久久久久 | 久热综合在线亚洲精品| 亚洲国产精品久久66| 在线免费观看亚洲| 亚洲成人一级电影| 亚洲综合色区中文字幕| 国产精品亚洲综合久久 | 亚洲av色香蕉一区二区三区 | 国产成人综合亚洲一区| 亚洲精品视频免费观看| 国产亚洲美女精品久久久2020| 亚洲人成伊人成综合网久久久| 好看的亚洲黄色经典| 亚洲日本一区二区| 亚洲女人影院想要爱| 亚洲va久久久久| 久久久久久久久无码精品亚洲日韩| 亚洲av综合av一区二区三区 | 亚洲精品NV久久久久久久久久| 久久久久国产亚洲AV麻豆| 国产亚洲人成网站观看| 亚洲激情在线观看| 亚洲乱码在线视频| 亚洲av无码专区在线观看亚| 亚洲AV无码乱码麻豆精品国产| 亚洲韩国—中文字幕| 久久精品国产亚洲77777| 国产成人精品亚洲2020| 久久精品国产亚洲av瑜伽|