0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

還能這樣?把 Python 自動(dòng)翻譯成 C++

電子設(shè)計(jì) ? 來(lái)源:電子設(shè)計(jì) ? 作者:電子設(shè)計(jì) ? 2020-12-10 18:29 ? 次閱讀

本文主要介紹在機(jī)器學(xué)習(xí)模型部署過(guò)程中,怎么樣快速得將python轉(zhuǎn)為C++。
來(lái)源:騰訊技術(shù)工程微信號(hào)
作者:byronhe,騰訊 WXG 開(kāi)發(fā)工程師

一、問(wèn)題背景

隨著深度學(xué)習(xí)的廣泛應(yīng)用,在搜索引擎/推薦系統(tǒng)/機(jī)器視覺(jué)等業(yè)務(wù)系統(tǒng)中,越來(lái)越多的深度學(xué)習(xí)模型部署到線上服務(wù)。

機(jī)器學(xué)習(xí)模型在離線訓(xùn)練時(shí),一般要將輸入的數(shù)據(jù)做特征工程預(yù)處理,再輸入模型在 TensorFlow PyTorch 等框架上做訓(xùn)練。

1.常見(jiàn)的特征工程邏輯

常見(jiàn)的特征工程邏輯有:

分箱/分桶 離散化

log/exp 對(duì)數(shù)/冪等 math numpy 常見(jiàn)數(shù)學(xué)運(yùn)算

特征縮放/歸一化/截?cái)?/p>

交叉特征生成

分詞匹配程度計(jì)算

字符串分隔匹配判斷 tong

缺省值填充等

數(shù)據(jù)平滑

onehot 編碼,hash 編碼等

這些特征工程代碼,當(dāng)然一般使用深度學(xué)習(xí)最主要的語(yǔ)言 python 實(shí)現(xiàn)。

二、業(yè)務(wù)痛點(diǎn)

離線訓(xùn)練完成,模型上線部署后,同樣要用 C++ 重新實(shí)現(xiàn) 這些 python 的特征工程邏輯代碼。

我們發(fā)現(xiàn),“用 C++ 重新實(shí)現(xiàn)” 這個(gè)步驟,給實(shí)際業(yè)務(wù)帶來(lái)了大量的問(wèn)題:

繁瑣,費(fèi)時(shí)費(fèi)力,極容易出現(xiàn) python 和 C++ 代碼不一致

不一致會(huì)直接影響模型在線上的效果,導(dǎo)致大盤(pán)業(yè)務(wù)指標(biāo)不如預(yù)期,產(chǎn)生各種 bad case

不一致難以發(fā)現(xiàn),無(wú)法測(cè)試,無(wú)法監(jiān)控,經(jīng)常要靠用戶(hù)投訴反饋,甚至大盤(pán)數(shù)據(jù)異常才能發(fā)現(xiàn)

1. 業(yè)界方案

針對(duì)這些問(wèn)題,我調(diào)研了這些業(yè)界方案:

《推薦系統(tǒng)中模型訓(xùn)練及使用流程的標(biāo)準(zhǔn)化》

《自主研發(fā)、不斷總結(jié)經(jīng)驗(yàn),美團(tuán)搜索推薦機(jī)器學(xué)習(xí)平臺(tái)》

《京東電商推薦系統(tǒng)實(shí)踐》

“模型線上線下一致性問(wèn)題對(duì)于模型效果非常重要,我們使用特征日志來(lái)實(shí)時(shí)記錄特征,保證特征的一致性。這樣離線處理的時(shí)候會(huì)把實(shí)時(shí)的用戶(hù)反饋,和特征日志做一個(gè)結(jié)合生成訓(xùn)練樣本,然后更新到模型訓(xùn)練平臺(tái)上,平臺(tái)更新之后在推送到線上,這樣整個(gè)排序形成了一個(gè)閉環(huán)?!?/p>

總結(jié)起來(lái),有幾種思路:

在線特征存儲(chǔ)起來(lái)給離線用

在線 C++ 代碼編譯成 so 導(dǎo)出給離線用

根據(jù)一份配置生成離線和在線代碼

提取公共代碼,加強(qiáng)代碼復(fù)用,等軟件工程手段,減少不一致

2. 自動(dòng)翻譯方案

(1) .已有方案的缺點(diǎn)

但這些思路都有各種缺點(diǎn):

所有在線請(qǐng)求的所有特征,這個(gè)存儲(chǔ)量數(shù)據(jù)量很大

算法改代碼需要等待后臺(tái)開(kāi)發(fā),降低了算法同學(xué)的工作效率

特征處理代碼的復(fù)雜度轉(zhuǎn)移到配置文件中,不一定能充分表達(dá),而且配置格式增加學(xué)習(xí)成本

就這邊真實(shí)離線特征處理代碼來(lái)看,大部分代碼都無(wú)法抽取出公共代碼做復(fù)用。

(2). 翻譯器

回到問(wèn)題出發(fā)點(diǎn)考慮,顯而易見(jiàn),這個(gè)問(wèn)題歸根結(jié)底就是需要一個(gè) “ python 到 c++ 的翻譯器 ” 。

那其實(shí) “翻譯器 Transpiler ” ,和編譯器解釋器類(lèi)似,也是個(gè)古老的熱門(mén)話題了,比如 WebAssembly, CoffeeScript ,Babel ,
Google Closure Compiler,f2c

于是一番搜索,發(fā)現(xiàn) python 到 C++ 的翻譯器也不少,其中 Pythran 是新興比較熱門(mén)的開(kāi)源項(xiàng)目。

于是一番嘗試后,借助 pythran,我們實(shí)現(xiàn)了:

一條命令 全自動(dòng)把 Python 翻譯成等價(jià) C++

嚴(yán)格等價(jià)保證改寫(xiě),徹底消除不一致

完全去掉重新實(shí)現(xiàn) 這塊工作量,后臺(tái)開(kāi)發(fā)成本降到 0 ,徹底解放生產(chǎn)力

算法同學(xué)繼續(xù)使用純 python,開(kāi)發(fā)效率無(wú)影響, 無(wú)學(xué)習(xí)成本

并能推廣到其他需要 python 改寫(xiě)成后臺(tái) C++ 代碼 的業(yè)務(wù)場(chǎng)景,解放生產(chǎn)力

三、pythran 的使用流程

(1). 安裝

一條命令安裝:

pip3 install pythran

(2). 寫(xiě) Python 代碼

下面這個(gè) python demo,是 pythran 官方 demo

import math
import numpy as np

def zero(n, m):
    return [[0]*n for col in range(m)]

#pythran export matrix_multiply(float list list, float list list)
def matrix_multiply(m0, m1):
    new_matrix = zero(len(m0),len(m1[0]))
    for i in range(len(m0)):
        for j in range(len(m1[0])):
            for k in range(len(m1)):
                new_matrix[i][j] += m0[i][k]*m1[k][j]
    return new_matrix

#pythran export arc_distance(float[], float[], float[], float[])
def arc_distance(theta_1, phi_1, theta_2, phi_2):
    """
    Calculates the pairwise arc distance
    between all points in vector a and b.
    """
    temp = (np.sin((theta_2-theta_1)/2)**2
           + np.cos(theta_1)*np.cos(theta_2) * np.sin((phi_2-phi_1)/2)**2)
    distance_matrix = 2 * np.arctan2(np.sqrt(temp), np.sqrt(1-temp))
    return distance_matrix


#pythran export dprod(int list, int list)
def dprod(l0,l1):
    """WoW, generator expression, zip and sum."""
    return sum(x * y for x, y in zip(l0, l1))


#pythran export get_age(int )
def get_age(age):
    if age <= 20:
        age_x = '0_20'
    elif age <= 25:
        age_x = '21_25'
    elif age <= 30:
        age_x = '26_30'
    elif age <= 35:
        age_x = '31_35'
    elif age <= 40:
        age_x = '36_40'
    elif age <= 45:
        age_x = '41_45'
    elif age <= 50:
        age_x = '46_50'
    else:
        age_x = '50+'
    return age_x

(3). Python 轉(zhuǎn)成 C++

一條命令完成翻譯

pythran -e demo.py -o  demo.hpp

(4). 寫(xiě) C++ 代碼調(diào)用

pythran/pythonic/ 目錄下是 python 標(biāo)準(zhǔn)庫(kù)的 C++ 等價(jià)實(shí)現(xiàn),翻譯出來(lái)的 C++ 代碼需要 include 這些頭文件

寫(xiě)個(gè) C++ 代碼調(diào)用

#include "demo.hpp"
#include "pythonic/numpy/random/rand.hpp"
#include 

using std::cout;
using std::endl;

int main() {
  pythonic::types::list> m0 = {{2.0, 3.0},
                                                             {4.0, 5.0}},
                                                       m1 = {{1.0, 2.0},
                                                             {3.0, 4.0}};
  cout << m0 << "*" << m1 << "/n=/n"
       << __pythran_demo::matrix_multiply()(m0, m1) << endl
       << endl;

  auto theta_1 = pythonic::numpy::random::rand(3),
       phi_1 = pythonic::numpy::random::rand(3),
       theta_2 = pythonic::numpy::random::rand(3),
       phi_2 = pythonic::numpy::random::rand(3);
  cout << "arc_distance " << theta_1 << "," << phi_1 << "," << theta_2 << ","
       << phi_2 << "/n=/n"
       << __pythran_demo::arc_distance()(theta_1, phi_1, theta_2, phi_2) << endl
       << endl;

  pythonic::types::list l0 = {2, 3}, l1 = {4, 5};
  cout << "dprod " << l0 << "," << l1 << "/n=/n"
       << __pythran_demo::dprod()(l0, l1) << endl
       << endl;

  cout << "get_age 30 = " << __pythran_demo::get_age()(30) << endl << endl;

  return 0;
}

(5). 編譯運(yùn)行

g++ -g -std=c++11 main.cpp -fopenmp -march=native -DUSE_XSIMD -I /usr/local/lib/python3.6/site-packages/pythran/ -o pythran_demo


./pythran_demo

四、pythran 的功能與特性

(1). 介紹

按官方定義,Pythran 是一個(gè) AOT (Ahead-Of-Time - 預(yù)先編譯) 編譯器。給科學(xué)計(jì)算的 python 加注解后,pythran 可以把 python 代碼變成接口相同的原生 python 模塊,大幅度提升性能。

并且 pythran 也可以利用 OpenMP 多核和 SIMD 指令集。

支持 python 3 和 Python 2.7 。

pythran 的 manual 挺詳細(xì):
https://pythran.readthedocs.io/en/latest/MANUAL.html

(2). 功能

pythran 并不支持完整的 python, 只支持 python 語(yǔ)言特性的一個(gè)子集:

polymorphic functions 多態(tài)函數(shù)(翻譯成 C++ 的泛型模板函數(shù))

lambda

list comprehension 列表推導(dǎo)式

map, reduce 等函數(shù)

dictionary, set, list 等數(shù)據(jù)結(jié)構(gòu)

exceptions 異常

file handling 文件處理

部分 numpy

不支持的功能:

classes 類(lèi)

polymorphic variables 可變類(lèi)型變量

(3). 支持的數(shù)據(jù)類(lèi)型和函數(shù)

pythran export 可以導(dǎo)出函數(shù)和全局變量。
支持導(dǎo)出的數(shù)據(jù)類(lèi)型,BNF 定義是:

  argument_type = basic_type
                  | (argument_type+)    # this is a tuple
                  | argument_type list    # this is a list
                  | argument_type set    # this is a set
                  | argument_type []+    # this is a ndarray, C-style
                  | argument_type [::]+    # this is a strided ndarray
                  | argument_type [:,...,:]+ # this is a ndarray, Cython style
                  | argument_type [:,...,3]+ # this is a ndarray, some dimension fixed
                  | argument_type:argument_type dict    # this is a dictionary

    basic_type = bool | byte | int | float | str | None | slice
               | uint8 | uint16 | uint32 | uint64 | uintp
               | int8 | int16 | int32 | int64 | intp
               | float32 | float64 | float128
               | complex64 | complex128 | complex256

可以看到基礎(chǔ)類(lèi)型相當(dāng)全面,支持各種 整數(shù),浮點(diǎn)數(shù),字符串,復(fù)數(shù)

復(fù)合類(lèi)型支持 tuple, list, set, dict, numpy.ndarray 等,

對(duì)應(yīng) C++ 代碼的類(lèi)型實(shí)現(xiàn)在 pythran/pythonic/include/types/ 下面,可以看到比如 dict 實(shí)際就是封裝了一下 std::unordered_map
https://pythran.readthedocs.i...
可以看到支持的 python 基礎(chǔ)庫(kù),其中常用于機(jī)器學(xué)習(xí)的 numpy 支持算比較完善。

五、pythran 的基本原理

和常見(jiàn)的編譯器/解釋器類(lèi)似, pythran 的架構(gòu)是分成 3 層:

python 代碼解析成抽象語(yǔ)法樹(shù) AST 。用 python 標(biāo)準(zhǔn)庫(kù)自帶的的 ast 模塊實(shí)現(xiàn)

代碼優(yōu)化。

在 AST 上做優(yōu)化,有多種 transformation pass,比如 deadcode_elimination 死代碼消除,loop_full_unrolling 循環(huán)展開(kāi) 等。還有 Function/Module/Node 級(jí)別的 Analysis,用來(lái)遍歷 AST 供 transformation 利用。

后端,實(shí)現(xiàn)代碼生成。目前有 2 個(gè)后端,Cxx / Python, Cxx 后端可以把 AST 轉(zhuǎn)成 C++ 代碼( Python 后端用來(lái)調(diào)試)。

目前看起來(lái) ,pythran 還欠缺的:

字符串處理能力欠缺,缺少 str.encode()/str.decode() 對(duì) utf8 的支持

缺少正則表達(dá)式 regex 支持

看文檔要自己加也不麻煩,看業(yè)務(wù)需要可以加。

審核編輯 黃昊宇

聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 人工智能
    +關(guān)注

    關(guān)注

    1792

    文章

    47373

    瀏覽量

    238861
  • C++
    C++
    +關(guān)注

    關(guān)注

    22

    文章

    2110

    瀏覽量

    73692
  • 機(jī)器學(xué)習(xí)

    關(guān)注

    66

    文章

    8423

    瀏覽量

    132746
  • python
    +關(guān)注

    關(guān)注

    56

    文章

    4797

    瀏覽量

    84787
收藏 人收藏

    評(píng)論

    相關(guān)推薦

    LLMWorld上線代碼翻譯新工具——問(wèn)丫·碼語(yǔ)翻譯俠,快來(lái)體驗(yàn)!

    應(yīng)用案例 aicode.llmworld.net 案例一 閱讀復(fù)雜算法,將計(jì)算機(jī)語(yǔ)言翻譯成自然語(yǔ)言和偽代碼,快速幫助用戶(hù)理解算法實(shí)現(xiàn)邏輯。 Input(C++): 正弦波信號(hào)進(jìn)行傅里葉變換,并輸出其頻域結(jié)果的C++
    的頭像 發(fā)表于 12-09 11:11 ?292次閱讀
    LLMWorld上線代碼<b class='flag-5'>翻譯</b>新工具——問(wèn)丫·碼語(yǔ)<b class='flag-5'>翻譯</b>俠,快來(lái)體驗(yàn)!

    同樣是函數(shù),在CC++中有什么區(qū)別

    ,即使沒(méi)有數(shù)據(jù)返回,也得寫(xiě) void。 第二個(gè)函數(shù)名。 C語(yǔ)言的函數(shù)名絕對(duì)不能重名,除了用上 weak 這樣的黑科技。同一個(gè)項(xiàng)目中,函數(shù)重名就會(huì)提示重復(fù)定義。 C++因?yàn)楹瘮?shù)重載的存在,函數(shù)名可以相同,只要參數(shù)有區(qū)別就行。這兩個(gè)
    的頭像 發(fā)表于 11-29 10:25 ?347次閱讀

    C語(yǔ)言和C++中結(jié)構(gòu)體的區(qū)別

    同樣是結(jié)構(gòu)體,看看在C語(yǔ)言和C++中有什么區(qū)別?
    的頭像 發(fā)表于 10-30 15:11 ?261次閱讀

    C7000優(yōu)化C/C++編譯器

    電子發(fā)燒友網(wǎng)站提供《C7000優(yōu)化C/C++編譯器.pdf》資料免費(fèi)下載
    發(fā)表于 10-30 09:45 ?0次下載
    <b class='flag-5'>C</b>7000優(yōu)化<b class='flag-5'>C</b>/<b class='flag-5'>C++</b>編譯器

    使用OpenVINO GenAI API在C++中構(gòu)建AI應(yīng)用程序

    許多桌面應(yīng)用程序是使用 C++ 開(kāi)發(fā)的,而將生成式AI(GenAI)功能集成到這些應(yīng)用程序中可能會(huì)很具有挑戰(zhàn)性,尤其是因?yàn)槭褂孟?Hugging Face 這樣Python 庫(kù)的復(fù)雜性。C
    的頭像 發(fā)表于 10-12 09:36 ?395次閱讀
    使用OpenVINO GenAI API在<b class='flag-5'>C++</b>中構(gòu)建AI應(yīng)用程序

    OpenVINO2024 C++推理使用技巧

    很多人都使用OpenVINO新版的C++ 或者Python的SDK,都覺(jué)得非常好用,OpenVINO2022之后的版本C++ SDK做了大量的優(yōu)化與整理,已經(jīng)是非常貼近開(kāi)發(fā)的使用習(xí)慣與推理方式。與OpenCV的Mat對(duì)象對(duì)接方式
    的頭像 發(fā)表于 07-26 09:20 ?956次閱讀

    C++語(yǔ)言基礎(chǔ)知識(shí)

    電子發(fā)燒友網(wǎng)站提供《C++語(yǔ)言基礎(chǔ)知識(shí).pdf》資料免費(fèi)下載
    發(fā)表于 07-19 10:58 ?7次下載

    C++中實(shí)現(xiàn)類(lèi)似instanceof的方法

    C++有多態(tài)與繼承,但是很多人開(kāi)始學(xué)習(xí)C++,有時(shí)候會(huì)面臨一個(gè)常見(jiàn)問(wèn)題,就是如何向下轉(zhuǎn)型,特別是不知道具體類(lèi)型的時(shí)候,這個(gè)時(shí)候就希望C++ 可以向Java或者Python中有insta
    的頭像 發(fā)表于 07-18 10:16 ?608次閱讀
    <b class='flag-5'>C++</b>中實(shí)現(xiàn)類(lèi)似instanceof的方法

    虹科直播 | 原來(lái)LIN總線故障還能這樣查?!教你LIN總線譯碼技巧及運(yùn)用!

    的。與此同時(shí),電壓數(shù)值正常與否,也只是判斷物理層是否正常的依據(jù)之一。在擁有多個(gè)從模塊的LIN總線上,想要準(zhǔn)確查找通訊故障根源,還需要將總線上的信號(hào)翻譯成更為可讀的信息。如
    的頭像 發(fā)表于 06-20 08:08 ?579次閱讀
    虹科直播 | 原來(lái)LIN總線故障<b class='flag-5'>還能</b><b class='flag-5'>這樣</b>查?!教你LIN總線譯碼技巧及運(yùn)用!

    使用 MISRA C++:2023? 避免基于范圍的 for 循環(huán)中的錯(cuò)誤

    在前兩篇博客中,我們?向您介紹了新的 MISRA C++ 標(biāo)準(zhǔn)?和?C++ 的歷史?。在這篇博客中,我們將仔細(xì)研究以 C++ 中?for?循環(huán)為中心的特定規(guī)則。
    的頭像 發(fā)表于 03-28 13:53 ?821次閱讀
    使用 MISRA <b class='flag-5'>C++</b>:2023? 避免基于范圍的 for 循環(huán)中的錯(cuò)誤

    求一種基于TRIZ理論的操控臺(tái)模塊鎖緊機(jī)構(gòu)設(shè)計(jì)方案

    TRIZ是俄文Teoriya Resheniya Izobreatatel-skikh Zadatch的縮寫(xiě),意思是發(fā)明問(wèn)題解決理論,翻譯成英文是Theory of Inventive Problem Solving[1-3],漢語(yǔ)譯作“萃智”。
    的頭像 發(fā)表于 02-29 14:16 ?359次閱讀
    求一種基于TRIZ理論的操控臺(tái)模塊鎖緊機(jī)構(gòu)設(shè)計(jì)方案

    c語(yǔ)言,c++,java,python區(qū)別

    C語(yǔ)言、C++、Java和Python是四種常見(jiàn)的編程語(yǔ)言,各有優(yōu)點(diǎn)和特點(diǎn)。 C語(yǔ)言: C語(yǔ)言是一種面向過(guò)程的編程語(yǔ)言。它具有底層的特性,能
    的頭像 發(fā)表于 02-05 14:11 ?2446次閱讀

    影響AI生態(tài)系統(tǒng)的七大主要趨勢(shì)

    過(guò)去,計(jì)算機(jī)只能在人類(lèi)語(yǔ)言首先被翻譯成代碼后才能理解。但通過(guò)使用NLP,機(jī)器能夠在文本保持其自然狀態(tài)的情況下獲取智能。
    的頭像 發(fā)表于 01-31 12:30 ?1691次閱讀
    影響AI生態(tài)系統(tǒng)的七大主要趨勢(shì)

    如何使用Python進(jìn)行圖像識(shí)別的自動(dòng)學(xué)習(xí)自動(dòng)訓(xùn)練?

    如何使用Python進(jìn)行圖像識(shí)別的自動(dòng)學(xué)習(xí)自動(dòng)訓(xùn)練? 使用Python進(jìn)行圖像識(shí)別的自動(dòng)學(xué)習(xí)和自動(dòng)
    的頭像 發(fā)表于 01-12 16:06 ?607次閱讀

    C++簡(jiǎn)史:C++是如何開(kāi)始的

    MISRA C++:2023,MISRA? C++ 標(biāo)準(zhǔn)的下一個(gè)版本,來(lái)了!為了幫助您做好準(zhǔn)備,我們介紹了 Perforce 首席技術(shù)支持工程師 Frank van den Beuken 博士撰寫(xiě)
    的頭像 發(fā)表于 01-11 09:00 ?619次閱讀
    <b class='flag-5'>C++</b>簡(jiǎn)史:<b class='flag-5'>C++</b>是如何開(kāi)始的