在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

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

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

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

編譯器可以為你生成高性能的代碼,但是你真的需要編譯器嗎?

電子工程師 ? 來(lái)源:lp ? 2019-03-11 09:35 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

編譯的目的是將源碼轉(zhuǎn)化為機(jī)器可識(shí)別的可執(zhí)行程序,在早期,每次編譯都需要重新構(gòu)建所有東西,后來(lái)人們意識(shí)到可以讓編譯器自動(dòng)完成一些工作,從而提升編譯效率。

但“編譯器不過是用于代碼生成的軟機(jī)器,你可以使用你想要的任何語(yǔ)言來(lái)生成代碼”,真的是必要的嗎?

誠(chéng)然,編譯器可以為你生成高性能的代碼,但是你真的需要編譯器嗎?另一種方法是用 Assembly 編寫程序,雖然有點(diǎn)夸大,但這種方法有兩個(gè)主要缺陷:

1. 匯編代碼不可移植;

2. 雖然在現(xiàn)代工具的輔助下變得容易了些,但 Assembly 編程仍然需要大量繁瑣的工作。

值得慶幸的是,我們都生活在二十一世紀(jì),這兩個(gè)問題都已得到解決。第一個(gè)解決方案是LLVM,最初,它意味著“低級(jí)虛擬機(jī)”,這正是我們可以確保可移植性的原因。簡(jiǎn)而言之,它需要用一些非常低級(jí)別的與硬件無(wú)關(guān)語(yǔ)言編寫的代碼,并為特定的硬件平臺(tái)返回一些高度優(yōu)化的原生代碼。使用 LLVM,我們既具有低級(jí)編程的強(qiáng)大功能,又具有面向硬件微優(yōu)化的自動(dòng)化功能。

第二個(gè)問題的解決方法是使用“腳本”語(yǔ)言,Scheme、Python、Perl,甚至 bash 或 AWK 都可以消除繁瑣的工作。

實(shí)驗(yàn)計(jì)劃

首先,讓我們生成一個(gè)完全內(nèi)聯(lián)展開的解決方案,并將其嵌入到基準(zhǔn)測(cè)試代碼中。該計(jì)劃如下:

1. 使用 Clang 為基準(zhǔn)生成 LLVM 中間代碼,該基準(zhǔn)用于測(cè)量 solve_5,一個(gè)不存在的函數(shù);

2. 使 Python 在 LLVM 中生成線性求解器(linear solver)代碼;

3. 使用 Python 腳本測(cè)試基準(zhǔn),用生成求解器替換 solve_5 調(diào)用;

4. 使用 LLVM 靜態(tài)編譯器將中間代碼轉(zhuǎn)換為機(jī)器代碼;

5. 使用 GNU 匯編器和 Clang 的鏈接器將機(jī)器代碼轉(zhuǎn)換為可執(zhí)行的二進(jìn)制文件。

這就是它在 Makefile 中的樣子:

Python 部分

我們需要 Python 中的線性求解器(linear solver),就像我們使用 C 和 C ++ 一樣,此處代碼為:

#thisgeneratesn-solverinLLVMcodewithLLVMCodeobjects.#NoLLVMstuffyet,justcompletelyPythonicsolutiondefsolve_linear_system(a_array,b_array,x_array,n_value):defa(i,j,n):ifn==n_value:returna_array[i*n_value+j]returna(i,j,n+1)*a(n,n,n+1)-a(i,n,n+1)*a(n,j,n+1)defb(i,n):ifn==n_value:returnb_array[i]returna(n,n,n+1)*b(i,n+1)-a(i,n,n+1)*b(n,n+1)defx(i):d=b(i,i+1)forjinrange(i):d-=a(i,j,i+1)*x_array[j]returnd/a(i,i,i+1)forkinrange(n_value):x_array[k]=x(k)returnx_array

當(dāng)我們用數(shù)字運(yùn)行時(shí),我們可以得到數(shù)字。但我們想要代碼,因此,我們需要制作一個(gè)假裝成數(shù)字的對(duì)象(Object)來(lái)探測(cè)算法。該對(duì)象記錄下算法想要執(zhí)行的每一個(gè)操作,并準(zhǔn)備好集成 LLVM 中間語(yǔ)言。

#thisisbasicallythewholeLLVMlayerI=0STACK=[]classLLVMCode:#theonlyconstructorfornowisbydouble*instructiondef__init__(self,io,code=''):self.io=ioself.code=codedef__getitem__(self,i):globalI,STACKcopy_code="%"+str(I+1)copy_code+="=getelementptrinboundsdouble,double*"copy_code+=self.io+",i64"+str(i)+" "copy_code+="%"+str(I+2)copy_code+="=loaddouble,double*%"+str(I+1)copy_code+=",align8 "I+=2STACK+=[I]returnLLVMCode(self.io,copy_code)def__setitem__(self,i,other_llvcode):globalI,STACKself.code+=other_llvcode.codeself.code+="%"+str(I+1)self.code+="=getelementptrinboundsdouble,double*"self.code+=self.io+",i64"+str(i)+" "self.code+="storedouble%"+str(I)self.code+=",double*%"+str(I+1)+",align8 "I+=1STACK=STACK[:-1]returnselfdefgeneral_arithmetics(self,operator,other_llvcode):globalI,STACKself.code+=other_llvcode.code;self.code+="%"+str(I+1)+"=f"+operatorself.code+="double%"+str(STACK[-2])+",%"self.code+=str(STACK[-1])+" ";I+=1STACK=STACK[:-2]+[I]returnselfdef__add__(self,other_llvcode):returnself.general_arithmetics('add',other_llvcode)def__sub__(self,other_llvcode):returnself.general_arithmetics('sub',other_llvcode)def__mul__(self,other_llvcode):returnself.general_arithmetics('mul',other_llvcode)def__div__(self,other_llvcode):returnself.general_arithmetics('div',other_llvcode)

接著,當(dāng)我們使用這種對(duì)象運(yùn)行求解器時(shí),我們得到了一個(gè)用 LLVM 中間語(yǔ)言編寫的全功能線性求解器。然后我們將其放入基準(zhǔn)代碼中進(jìn)行速度測(cè)試(看它有多快)。

LLVM 中的指令有編號(hào),我們希望保存枚舉,因此將代碼插入到基準(zhǔn)測(cè)試中的函數(shù)很重要,但也不是很復(fù)雜。

#thisreplacesthefunctioncall#andupdatesalltheinstructions'indicesdefreplace_call(text,line,params):globalI,STACK#'%12'->12I=int(''.join([xiforxiinparams[2]ifxi.isdigit()]))first_instruction_to_replace=I+1STACK=[]replacement=solve_linear_system(LLVMCode(params[0]),LLVMCode(params[1]),LLVMCode(params[2]),5).codedelta_instruction=I-first_instruction_to_replace+1foriinxrange(first_instruction_to_replace,sys.maxint):not_found=sum([text.find('%'+str(i)+c)==-1forcinPOSSIBLE_CHARS_NUMBER_FOLLOWS_WITH])ifnot_found==4:#thelastinstructionhasalreadybeensubstitutedbreaknew_i=i+delta_instructionforcinPOSSIBLE_CHARS_NUMBER_FOLLOWS_WITH:#substituteinstructionnumbertext=text.replace('%'+str(i)+c,'%'+str(new_i)+c)returntext.replace(line,replacement)

實(shí)現(xiàn)解算器的整段代碼提供了 Python-to-LLVM 層,其中代碼插入只有 100 行!

另附 GitHub 鏈接:

https://github.com/akalenuk/wordsandbuttons/blob/master/exp/python_to_llvm/exp_embed_on_call/substitute_solver_call.py

基準(zhǔn)

基準(zhǔn)測(cè)試本身在 C 中。當(dāng)我們運(yùn)行 Makefile 時(shí),它對(duì) solve_5 的調(diào)用被 Python 生成的 LLVM 代碼所取代。

Step 1. Benchmark C source code

Step 2. LLVM 匯編語(yǔ)言

Step 3. 調(diào)用替換后的 LLVM

Step 4. 本地優(yōu)化裝配

最值得注意的是 Python 腳本生成的超冗長(zhǎng)中間代碼如何變成一些非常緊湊且非常有效的硬件代碼。同時(shí)它也是高度標(biāo)量化的,但它是否足以與 C 和 C++ 的解決方案競(jìng)爭(zhēng)呢?

以下是三種情況的近似數(shù)字(帶有技巧的 C、C++ 與基于 LLVM 的 Python 的性能對(duì)比):

1. C 的技巧對(duì) Clang 來(lái)說(shuō)并不適用,因此測(cè)量 GCC 版本,其平均運(yùn)行大約 70 毫秒;

2. C++ 版本是用 Clang 構(gòu)建的,運(yùn)行時(shí)間為 60 毫秒;

3. Python 版本(此處描述的版本)僅運(yùn)行 55 毫秒。

當(dāng)然,這種加速并不是關(guān)鍵,但這表明你可以用 Python 編寫出勝過用 C 或 C++ 編寫的程序。這也就暗示你不必學(xué)習(xí)一些特殊語(yǔ)言來(lái)創(chuàng)建高性能的應(yīng)用程序或庫(kù)。

結(jié)論

快速編譯語(yǔ)言和慢速腳本語(yǔ)言之間的對(duì)立不過是虛張聲勢(shì)。原生代碼生成的可能不是核心功能,而是類似于可插拔選項(xiàng)。像是Python 編譯器Numba或Lua 的Terra,其優(yōu)勢(shì)就在于你可以用一種語(yǔ)言進(jìn)行研究和快速原型設(shè)計(jì),然后使用相同的語(yǔ)言生成高性能的代碼。

高性能計(jì)算沒有理由保留編譯語(yǔ)言的特權(quán),編譯器只是用于代碼生成的軟機(jī)器。你可以使用你想要的任何語(yǔ)言生成代碼,我相信如果你愿意,你可以教 Matlab 生成超快的 LLVM 代碼。

本文涉及的所有測(cè)試均在 Intel(R)Core(TM)i7-7700HQ CPU @ 2.80GHz 上進(jìn)行,代碼使用 Clang 3.8.0-2ubuntu4 和 g++5.4.0 編譯。

基準(zhǔn)測(cè)試源代碼:

https://github.com/akalenuk/wordsandbuttons/tree/master/exp/python_to_llvm


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

    關(guān)注

    30

    文章

    4893

    瀏覽量

    70444
  • 編譯器
    +關(guān)注

    關(guān)注

    1

    文章

    1659

    瀏覽量

    50053
  • python
    +關(guān)注

    關(guān)注

    56

    文章

    4825

    瀏覽量

    86456

原文標(biāo)題:都有Python了,還要什么編譯器!

文章出處:【微信號(hào):rgznai100,微信公眾號(hào):rgznai100】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評(píng)論

    相關(guān)推薦
    熱點(diǎn)推薦

    如何編寫有利于編譯器優(yōu)化的代碼

    對(duì)于嵌入式系統(tǒng),最終代碼的體積和效率取決于由編譯器生成的可執(zhí)行代碼,而非開發(fā)人員編寫的源代碼但是
    發(fā)表于 11-09 10:31 ?1532次閱讀
    如何編寫有利于<b class='flag-5'>編譯器</b>優(yōu)化的<b class='flag-5'>代碼</b>

    Loop Interchange如何幫助編譯器生成更高效的可執(zhí)行代碼

    C/C++代碼編譯時(shí),編譯器將源碼翻譯成CPU可識(shí)別的指令序列并生成可執(zhí)行代碼,而最終代碼的運(yùn)
    發(fā)表于 08-03 10:56 ?611次閱讀

    基于CoSy的編譯器開發(fā)的研究

    CoSy是ACE公司開發(fā)的編譯器構(gòu)造框架[1]。它提供共享工具和引擎來(lái)構(gòu)造編譯器編譯器開發(fā)者只專注于目標(biāo)機(jī)相關(guān)代碼的開發(fā)。CoSy框架生成
    發(fā)表于 08-19 17:49 ?0次下載
    基于CoSy的<b class='flag-5'>編譯器</b>開發(fā)的研究

    編譯器原理到底是怎樣的帶你簡(jiǎn)單的了解編譯器原理

    編程語(yǔ)言是怎樣工作的 理解編譯器內(nèi)部原理,可以更高效利用它。按照編譯的工作順序,逐步深入編程語(yǔ)言和編譯器是怎樣工作的。本文有大量的鏈接
    的頭像 發(fā)表于 12-23 17:25 ?1.2w次閱讀

    解答編譯器是怎樣運(yùn)行的

    對(duì)于程序員來(lái)說(shuō)編譯器是非常熟悉的,每天都在用,但是當(dāng)你在點(diǎn)擊“Run”這個(gè)按鈕或者執(zhí)行編譯命令時(shí)知道編譯器是怎樣工作的嗎?
    的頭像 發(fā)表于 03-09 15:20 ?3038次閱讀

    王垠談編譯器

    由于早期的 Lisp 編譯器生成代碼效率普遍低下,成為了 Lisp 失敗的主要原因之一。而現(xiàn)在的高性能 Lisp 編譯器(比
    的頭像 發(fā)表于 03-30 10:45 ?2291次閱讀

    CompCert編譯器目標(biāo)代碼生成機(jī)制研究綜述

    對(duì) Compcert編譯器目標(biāo)代碼生成機(jī)制進(jìn)行剖析,主要介紹其設(shè)計(jì)邏輯、翻譯過程、語(yǔ)義保持性以及代碼結(jié)構(gòu),并給出了 Compcert編譯器
    發(fā)表于 05-07 10:17 ?7次下載

    如何編寫有利于編譯器優(yōu)化的代碼

    對(duì)于嵌入式系統(tǒng),最終代碼的體積和效率取決于由編譯器生成的可執(zhí)行代碼,而非開發(fā)人員編寫的源代碼但是
    的頭像 發(fā)表于 03-29 15:58 ?1940次閱讀
    如何編寫有利于<b class='flag-5'>編譯器</b>優(yōu)化的<b class='flag-5'>代碼</b>

    交叉編譯器安裝教程

    ,所以我們需要一個(gè)在 X86 架構(gòu)的 PC 上運(yùn)行,可以編譯 ARM 架構(gòu)代碼的 GCC 編譯器,這個(gè)
    的頭像 發(fā)表于 09-29 09:12 ?3969次閱讀

    編譯器的優(yōu)化選項(xiàng)

    這一點(diǎn),需要了解編譯器的能力和限制;第三,要了解硬件的運(yùn)行方式,針對(duì)硬件特性進(jìn)行優(yōu)化。本文著重展開第二點(diǎn)和第三點(diǎn)。 簡(jiǎn)單認(rèn)識(shí)編譯器 要寫出高性能
    的頭像 發(fā)表于 11-24 15:37 ?1312次閱讀
    <b class='flag-5'>編譯器</b>的優(yōu)化選項(xiàng)

    Triton編譯器與其他編譯器的比較

    的GPU編程框架,使開發(fā)者能夠編寫出接近手工優(yōu)化的高性能GPU內(nèi)核。 其他編譯器 (如GCC、Clang、MSVC等): 定位:通用編譯器,支持多種編程語(yǔ)言,廣泛應(yīng)用于各種軟件開發(fā)場(chǎng)景。 目標(biāo):提供穩(wěn)定、高效的
    的頭像 發(fā)表于 12-24 17:25 ?946次閱讀

    Triton編譯器的優(yōu)化技巧

    在現(xiàn)代計(jì)算環(huán)境中,編譯器性能對(duì)于軟件的運(yùn)行效率至關(guān)重要。Triton 編譯器作為一個(gè)先進(jìn)的編譯器框架,提供了一系列的優(yōu)化技術(shù),以確保生成
    的頭像 發(fā)表于 12-25 09:09 ?905次閱讀

    Triton編譯器高性能計(jì)算中的應(yīng)用

    先進(jìn)的編譯技術(shù),為高性能計(jì)算提供了強(qiáng)大的支持。 Triton編譯器簡(jiǎn)介 Triton編譯器是一種開源的編譯器框架,旨在為異構(gòu)計(jì)算環(huán)境提供高效
    的頭像 發(fā)表于 12-25 09:11 ?903次閱讀

    Triton編譯器與GPU編程的結(jié)合應(yīng)用

    Triton編譯器簡(jiǎn)介 Triton編譯器是一種針對(duì)并行計(jì)算優(yōu)化的編譯器,它能夠自動(dòng)將高級(jí)語(yǔ)言代碼轉(zhuǎn)換為針對(duì)特定硬件優(yōu)化的低級(jí)代碼。Trit
    的頭像 發(fā)表于 12-25 09:13 ?779次閱讀

    什么樣的代碼會(huì)被編譯器優(yōu)化

    現(xiàn)在的編譯器有多智能,可能辛辛苦苦寫的代碼,在編譯器看來(lái)就是幾句廢話,直接被刪除掉。
    的頭像 發(fā)表于 01-16 16:38 ?551次閱讀
    主站蜘蛛池模板: 天天插天天舔 | 久久国产乱子伦精品免费强 | 香蕉视频国产在线观看 | 久久草在线视频国产一 | 年轻人影院www你懂的 | 日本中文在线三级在线播放 | 欧美久久天天综合香蕉伊 | 7m凹凸精品分类大全免费 | 亚洲精品久久久久午夜福 | 簧片视频在线观看 | 性欧美高清极品猛交 | 女生张开腿让男人桶 | 中文字幕卡二和卡三的视频 | 手机看片福利盒子久久 | 美女扒开尿囗给男人玩的动图 | bt在线www天堂资源网 | a久久| 天天插天天射 | 国产黄色高清视频 | 四虎在线精品 | 亚洲毛片网 | 永久精品免费影院在线观看网站 | 俺来也婷婷 | 国产黄色录像视频 | 成人区精品一区二区毛片不卡 | 亚洲高清视频一区 | 午夜免费伦费影视在线观看 | 国产精品三级在线 | 五月激情久久 | 青青草99热久久 | 欧美特黄一级视频 | 在线免费观看黄色小视频 | 亚洲乱码卡一卡二卡三 | 人人舔| 久久综合五月婷婷 | 日韩成人黄色 | 老色网站 | 精品久久久久久国产免费了 | 免费一级在线 | 日本免费大黄在线观看 | 伊人2233|