一区二区三区三上|欧美在线视频五区|国产午夜无码在线观看视频|亚洲国产裸体网站|无码成年人影视|亚洲AV亚洲AV|成人开心激情五月|欧美性爱内射视频|超碰人人干人人上|一区二区无码三区亚洲人区久久精品

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

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

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

深度學(xué)習(xí)編譯器之Layerout Transform優(yōu)化

jf_pmFSk4VX ? 來源:GiantPandaCV ? 2023-05-18 17:32 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

在本文的描述中,存在一些接口和Interface的混用,這兩個(gè)是一樣的都表示MLIR的Interface。

0x0. 背景

繼續(xù)深度學(xué)習(xí)編譯器的優(yōu)化工作解讀,本篇文章要介紹的是OneFlow系統(tǒng)中如何基于MLIR實(shí)現(xiàn)Layerout Transform。在2D卷積神經(jīng)網(wǎng)絡(luò)中,除了NCHW數(shù)據(jù)格式之外一般還存在NHWC的數(shù)據(jù)格式,對(duì)于卷積操作來說使用NHWC格式進(jìn)行計(jì)算可能會(huì)獲得更好的性能。

但深度學(xué)習(xí)網(wǎng)絡(luò)的訓(xùn)練一般來說是采用NCHW進(jìn)行的,我們一般只有在推理時(shí)才做NCHW到NHWC的Layerout Transform。這里存在兩個(gè)問題:首先對(duì)于一個(gè)算子比如Conv2D,它以NCHW方式訓(xùn)練時(shí)保存的權(quán)重格式是[out_channels, in_channels, *kernel_size],但是要以NHWC格式進(jìn)行推理時(shí)我們需要對(duì)權(quán)重的格式進(jìn)行轉(zhuǎn)換;然后對(duì)于沒有權(quán)重的算子來說,我們也需要盡量的讓算子支持NHWC的運(yùn)算,來減少因?yàn)榫矸e算子前后插入的Transpose操作帶來的額外開銷。舉個(gè)例子,假設(shè)有如下的一個(gè)小網(wǎng)絡(luò) x->conv->relu->conv->relu->out,如果我們要以NHWC格式執(zhí)行那么我們除了對(duì)2個(gè)卷積的權(quán)重進(jìn)行改動(dòng)之外,我們還需要在conv前后插入transpose來修改輸入到conv算子的數(shù)據(jù)格式,也就是x->transpose(0, 2, 3, 1)->conv->transpose(0, 3, 1, 2) -> relu -> transpose(0, 2, 3, 1)->conv->transpose(0, 3, 1, 2) -> relu->out。然后細(xì)心的讀者可以發(fā)現(xiàn),實(shí)際上這里存在很多冗余的Transpose,因?yàn)镽eLU是支持以NHWC格式進(jìn)行運(yùn)算的,那么這個(gè)網(wǎng)絡(luò)可以化簡(jiǎn)為x->transpose(0, 2, 3, 1)->conv->relu->conv->relu->transpose(0, 3, 1, 2)->out。這樣可以減少一半的Transpose Op開銷。

之所以要做transpose的化簡(jiǎn)是因?yàn)閠ranspose算子本身也有運(yùn)行以及調(diào)度的開銷,如果我們不盡量減少transpose的個(gè)數(shù),那么因?yàn)楦挠肗HWC帶來的計(jì)算加速可能會(huì)被 Transpose 的開銷掩蓋住。我們基于OneFlow實(shí)現(xiàn)了上述的Layerout Transform優(yōu)化,以下給出測(cè)試結(jié)果。

在V100上對(duì)這個(gè)優(yōu)化進(jìn)行了測(cè)試,測(cè)試代碼見 https://github.com/Oneflow-Inc/oneflow/blob/master/oneflow/ir/test/OneFlow/auto_nhwc/test_resnet101_benchmark.py ,性能結(jié)果如下:

開啟nn.Graph的AMP選項(xiàng)。

網(wǎng)絡(luò)選取ResNet101,對(duì)其做前向推理。

batch_size nchw auto nhwc
16 14s 13s
32 24s 22s
64 44s 38s

在BatchSize=64時(shí)得到了13.6%的加速,隨著BatchSize減少加速比會(huì)減小,但始終會(huì)保持一些加速。需要注意的是,這里對(duì)權(quán)重參數(shù)部分提前進(jìn)行了transpose,所以這部分是沒有額外開銷的。實(shí)際上,我們采用了常量折疊的方式來完成,這個(gè)下篇文章再講。

0x1. 實(shí)現(xiàn)解析

在實(shí)現(xiàn)上主要需要搞定3個(gè)問題,第一個(gè)是如何確定哪些算子支持NHWC的運(yùn)算,第二個(gè)是插入Transpose算子,第三個(gè)是消除多余的Transpose對(duì)。

0x1.1 基于Interface確定哪些算子支持NHWC運(yùn)算

在OneFlow中如果我們要讓某個(gè)Op支持NHWC的計(jì)算,只需在Op定義時(shí)聲明一個(gè)NCHWCompatibleInterface。以卷積為例:

defOneFlow_Conv2DOp:OneFlow_ConvolutionBaseOp<"conv2d",?[NoMemoryEffect,?AttrSizedOperandSegments,?DeclareOpInterfaceMethods,DeclareOpInterfaceMethods]>{}

這里的 DeclareOpInterfaceMethods 表示這個(gè) Operator 實(shí)現(xiàn)了 NCHWCompatibleInterface 接口,該接口定義了與 NCHW 格式兼容的 Operator 需要實(shí)現(xiàn)的方法。

我們想讓其它的任意 Op 支持 NHWC 的運(yùn)算,只需要定義這個(gè)接口并且重寫這個(gè)接口的成員函數(shù)即可,接下來我們看一下NCHWCompatibleInterface 的定義。

defNCHWCompatibleInterface:OpInterface<"NCHWCompatible">{
letdescription=[{
InterfaceofNCHWcompatibility
}];

letmethods=[
InterfaceMethod<"",
????????"bool",?"IsNCHW",?(ins)
????>,
InterfaceMethod<"Create?NHWC?op?and?return?the?new?op's?results?to?be?transposed",
????????"llvm::SmallVector","NchwToNhwc",(ins"llvm::SmallVector":$transposed_inputs,"PatternRewriter&":$rewriter)
>,
InterfaceMethod<"",
????????"llvm::DenseSet","OperandsToTranspose",(ins)
>,
InterfaceMethod<"",
????????"llvm::DenseSet","ResultsToTranspose",(ins)
>,
];
letcppNamespace="::oneflow";
}

這個(gè)接口繼承自 OpInterface 接口, OpInterface 是 MLIR 框架中描述 Operator Interface 的基類。NCHWCompatibleInterface 表示一個(gè)與 NCHW 格式兼容的 Operator Interface。NCHWCompatibleInterface定義了幾個(gè)方法:

IsNCHW: 返回一個(gè) bool 值, 表示當(dāng)前的 Operator 在什么條件下是處理輸入為 NCHW 格式的數(shù)據(jù)。

NchwToNhwc: 接受 Transpose 后的輸入和重寫器 (rewriter), 用于從 NCHW 格式轉(zhuǎn)換為 NHWC 格式。

OperandsToTranspose: 返回需要 Transpose 的輸入值集合。

ResultsToTranspose:返回需要 Transpose 的輸出值集合。

接下來我們看一下Conv2D Op對(duì)應(yīng)的 NCHWCompatibleInterface 接口實(shí)現(xiàn):

boolConv2DOp::IsNCHW(){returnthis->getDataFormat().str()=="channels_first";}

llvm::DenseSetConv2DOp::OperandsToTranspose(){
if(this->get_addToOutput()){
return{this->getIn(),this->getWeight(),this->get_addToOutput()};
}else{
return{this->getIn(),this->getWeight()};
}
}

llvm::DenseSetConv2DOp::ResultsToTranspose(){return{this->getOut()};}

llvm::SmallVectorConv2DOp::NchwToNhwc(llvm::SmallVectorvalue,
PatternRewriter&rewriter){
autoconv_op=*this;
SmallVectoroperands;
operands.push_back(value[0]);
operands.push_back(value[1]);
if(conv_op.getBias())operands.push_back(conv_op.getBias());
if(this->get_addToOutput()){operands.push_back(value[2]);}
NamedAttrListattributes=conv_op->getAttrs();
attributes.set(conv_op.getDataFormatAttrName(),rewriter.getStringAttr("channels_last"));
autores=rewriter
.create(conv_op.getLoc(),getNHWCResultTypes(conv_op),operands,
attributes)
->getResults();
llvm::SmallVectorresults;
results.push_back(res[0]);
returnresults;
}

其中,IsNCHW 方法返回一個(gè) bool 值,表示該 Conv2DOp Operation 是否使用 NCHW 格式。它通過檢查 Operation 的data_format 屬性來判斷。OperandsToTranspose 方法返回需要 Transpose 的輸入值集合。對(duì)于 Conv2DOp 來說,主要輸入包括input、weight、bias(可選) 和 addto_output(可選),其中bias不需要 Transpose,并且這個(gè)addto_output是OneFlow的一個(gè)特殊的輸出用來做算子融合讀者可以忽略。

ResultsToTranspose 方法返回需要 Transpose 的輸出值集合。對(duì)于 Conv2DOp 來說,僅有一個(gè)輸出, 所以返回輸出特征圖的值。NchwToNhwc 方法接受 NCHW 格式的輸入值和重寫器,并返回 NHWC 格式的結(jié)果值。它通過創(chuàng)建一個(gè)新的 Conv2DOp Operation, 并將 data_format 屬性設(shè)置為 channels_last, 來實(shí)現(xiàn)從 NCHW 到 NHWC 的轉(zhuǎn)換。

0x1.2 插入Transpose算子

接下來就是貪心的給網(wǎng)絡(luò)里的算子插入Transpose算子,這里的思路是我們盡可能的對(duì)網(wǎng)絡(luò)里面的所有算子都前后分別插入一個(gè)Transpose,這樣的話在消除Transopose對(duì)的時(shí)候才能獲得最優(yōu)的解。給網(wǎng)絡(luò)中的算子插入Transpose的邏輯如下面的Pattern代碼所述:

structAutoNhwcPattern:publicOpInterfaceRewritePattern{
explicitAutoNhwcPattern(mlir::MLIRContext*context)
:OpInterfaceRewritePattern(context,/*benefit=*/1){}

public:
LogicalResultmatchAndRewrite(NCHWCompatibleop,PatternRewriter&rewriter)constoverride{
if(op->hasTrait()){
for(mlir::Valueoperand:op.OperandsToTranspose()){
if(operand.getType().cast().getShape().size()!=4){
returnfailure();
}
}
constautodevice_name=OpTrait::IsOpConfCompatible::getDeviceTag(op)
.cast()
.getValue()
.str();
if(device_name=="cpu"){returnfailure();}
}
llvm::SmallVectorperm=getChannelLastTransposePerm();
llvm::SmallVectorresult_perm=getChannelFirstTransposePerm();

NamedAttrListtranspose_attributes;
if(InitTransposeAttributes(op,transpose_attributes,rewriter).succeeded()){
transpose_attributes.append(llvm::StringRef("perm"),getSI32ArrayAttr(rewriter,perm));
}else{
returnfailure();
}
//whenopophasnosenseofdata_formatandpreopistranspose,wegreedilyinserttranspose
//intothisop,seekingmoreopportunitiestoeliminatetransposepattern.
constboolgreedily_transpose_flag=!op.IsNCHW()&&IsInsertTransposeOpBefore(op,rewriter);

if(op.IsNCHW()||greedily_transpose_flag){
//createtransposeopforinputoperand
SmallVectortranposed_operands;
llvm::DenseSetoperand_transpose=op.OperandsToTranspose();
intnum_transposed_operand=0;
for(Valueoperand:op->getOperands()){
if(operand_transpose.find(operand)!=operand_transpose.end()){
SmallVectorinput_res=getInputOperandTransposeOp(
op,operand,transpose_attributes,num_transposed_operand,rewriter);
tranposed_operands.push_back(input_res[0]);
num_transposed_operand+=1;
}
}
//createNHWCop
SmallVectorcreated_results=op.NchwToNhwc(tranposed_operands,rewriter);
//createtransposeopforresults
intnum_transposed_result=0;
transpose_attributes.set(llvm::StringRef("perm"),getSI32ArrayAttr(rewriter,result_perm));
llvm::DenseSettranspose_result=op.ResultsToTranspose();

for(Valueresult:op->getOpResults()){
if(transpose_result.find(result)!=transpose_result.end()){
if(autoresult_transpose_op=
getResultTransposeOp(op,created_results[num_transposed_result],
transpose_attributes,num_transposed_result,rewriter)){
result.replaceAllUsesWith(result_transpose_op);
num_transposed_result+=1;
}else{
returnfailure();
}
}
}
}
returnsuccess();
}
};

首先 AutoNhwcPattern 類繼承自 OpInterfaceRewritePattern,OpInterfaceRewritePattern 是一個(gè)用于重寫 Operation 的基類。AutoNhwcPattern 針對(duì)實(shí)現(xiàn)了 NCHWCompatible Interface 的 Operation 進(jìn)行重寫,以實(shí)現(xiàn) NCHW 到 NHWC 的格式轉(zhuǎn)換。然后,AutoNhwcPattern 重寫了 matchAndRewrite 方法。該方法會(huì)在遇到 NCHWCompatible Interface 的 Operation 時(shí)被調(diào)用,來實(shí)現(xiàn)從 NCHW 到 NHWC 的轉(zhuǎn)換。接下來,matchAndRewrite 方法首先會(huì)檢查 Operation 是否滿足轉(zhuǎn)換條件,如是否 4 維、是否在 CPU 設(shè)備上等。

如果不滿足則返回 failure。如果滿足, matchAndRewrite 方法會(huì)獲取 NCHW 到NHWC 和 NHWC 到 NCHW 的轉(zhuǎn)換順序。并初始化 Transpose Operation 的屬性。然后對(duì)于當(dāng)前 Op 是 NCHW 格式或者這個(gè) Op 的前一個(gè) Op 是Transpose Op,這里都進(jìn)行插入 Transpose Op的操作來獲得更多的優(yōu)化機(jī)會(huì)。

這里還涉及到幾個(gè)相關(guān)的工具函數(shù),我們也解釋一下:

llvm::SmallVectorgetChannelLastTransposePerm(){return{0,2,3,1};}

llvm::SmallVectorgetChannelFirstTransposePerm(){return{0,3,1,2};}

llvm::SmallVectorgetInputOperandTransposeOp(NCHWCompatibleop,Valueval,
NamedAttrListtranspose_attributes,
intnum_transposed_operand,
PatternRewriter&rewriter){
std::stringtranspose_name=OpTrait::IsOpConfCompatible::getOpName(op).str()
+"_transpose_input_"+std::to_string(num_transposed_operand);
transpose_attributes.set(llvm::IsOpConfCompatible::getOpNameAttr()),
rewriter.getStringAttr(transpose_name));
SmallVectorinput_operands;
input_operands.push_back(val);
autores=rewriter
.create(op.getLoc(),getNHWCType(val.getType()),
input_operands,transpose_attributes)
->getResults();
returnres;
}

TransposeOpgetResultTransposeOp(NCHWCompatibleop,Valueval,NamedAttrListtranspose_attributes,
intnum_transposed_result,PatternRewriter&rewriter){
std::stringtranspose_name=OpTrait::IsOpConfCompatible::getOpName(op).str()
+"_transpose_output_"+std::to_string(num_transposed_result);
transpose_attributes.set(llvm::IsOpConfCompatible::getOpNameAttr()),
rewriter.getStringAttr(transpose_name));
SmallVectoroperands;
operands.push_back(val);
TransposeOptranspose_op=rewriter.create(
op.getLoc(),getNCHWType(val.getType()),operands,transpose_attributes);
returntranspose_op;
}

boolIsInsertTransposeOpBefore(NCHWCompatibleop,PatternRewriter&rewriter){
boolinsert_transpose_op_flag=false;
for(mlir::Valueoperand:op->getOperands()){
TransposeOptransposeInputOp=operand.getDefiningOp();
if(!transposeInputOp)continue;
constautoperm=transposeInputOp.getPermAttr();
if(perm.size()==4&&perm[0]==rewriter.getSI32IntegerAttr(0)
&&perm[1]==rewriter.getSI32IntegerAttr(3)&&perm[2]==rewriter.getSI32IntegerAttr(1)
&&perm[3]==rewriter.getSI32IntegerAttr(2)){
insert_transpose_op_flag=true;
break;
}
}
returninsert_transpose_op_flag;
}

其中 getChannelLastTransposePerm 和 getChannelFirstTransposePerm 方法分別返回 NHWC 到 NCHW 和 NCHW 到NHWC 的轉(zhuǎn)換順序。getInputOperandTransposeOp 方法為 Operation 的輸入創(chuàng)建一個(gè)Transpose Operation。它使用輸入值、Transpose屬性 和 重寫器創(chuàng)建一個(gè) TransposeOp , 并返回其結(jié)果。

類似的,getResultTransposeOp 方法為 Operation 的輸出創(chuàng)建一個(gè)Transpose Operation。它使用輸出值、Transpose屬性和重寫器創(chuàng)建一個(gè)TransposeOp,并返回該Operation。IsInsertTransposeOpBefore方法檢查Operation的輸入是否已有 Transpose Operation。如果有,并且該 Transpose Operation 將 NHWC 轉(zhuǎn)為 NCHW, 則返回 true, 否則返回false。

0x1.3 消除多余的Transpose對(duì)

接下來,我們需要把插入Transpose Op的圖中所有相鄰的Transpose對(duì)盡可能的消除,代碼實(shí)現(xiàn)如下:

boolIsRedundantTransposeMatch(ArrayAttrpre,ArrayAttrafe,mlir::PatternRewriter&rewriter){
constautoprePerm=pre.getValue().vec();
constautoafePerm=afe.getValue().vec();
if(prePerm.size()==4&&afePerm.size()==4){
//handlenchw->nhwc->nchw:(0,2,3,1)->(0,3,1,2)
if(prePerm[0]==afePerm[0]&&prePerm[1]==afePerm[3]&&prePerm[2]==afePerm[1]
&&prePerm[3]==afePerm[2]&&prePerm[0]==rewriter.getSI32IntegerAttr(0)
&&prePerm[1]==rewriter.getSI32IntegerAttr(2)
&&prePerm[2]==rewriter.getSI32IntegerAttr(3)
&&prePerm[3]==rewriter.getSI32IntegerAttr(1))
returntrue;
//handlenhwc->nchw->nhwc:(0,3,1,2)->(0,2,3,1)
if(prePerm[0]==afePerm[0]&&prePerm[1]==afePerm[2]&&prePerm[2]==afePerm[3]
&&prePerm[3]==afePerm[1]&&prePerm[0]==rewriter.getSI32IntegerAttr(0)
&&prePerm[1]==rewriter.getSI32IntegerAttr(3)
&&prePerm[2]==rewriter.getSI32IntegerAttr(1)
&&prePerm[3]==rewriter.getSI32IntegerAttr(2))
returntrue;
}
returnfalse;
}

structAutoNhwcEliminateRedundantTransposePattern:publicmlir::OpRewritePattern{
explicitAutoNhwcEliminateRedundantTransposePattern(mlir::MLIRContext*context)
:OpRewritePattern(context,/*benefit=*/1){}
mlir::LogicalResultmatchAndRewrite(TransposeOpop,
mlir::PatternRewriter&rewriter)constoverride{
mlir::ValuetransposeInput=op.getOperand();
TransposeOptransposeInputOp=transposeInput.getDefiningOp();

if(!transposeInputOp
||!IsRedundantTransposeMatch(op.getPermAttr(),transposeInputOp.getPermAttr(),rewriter)){
returnfailure();
}
rewriter.replaceOp(op,{transposeInputOp.getOperand()});
returnsuccess();
}
};

IsRedundantTransposeMatch 方法檢查兩個(gè) Transpose Operation的順序是否會(huì)導(dǎo)致冗余。它通過比較兩個(gè) Transpose 的 perm 屬性來判斷。類似 AutoNhwcPattern ,AutoNhwcEliminateRedundantTransposePattern 類繼承自 OpRewritePattern 。它對(duì)TransposeOp 進(jìn)行重寫以實(shí)現(xiàn) Transpose 消除。如果順序是 NHWC->NCHW->NHWC 或NCHW->NHWC->NCHW , 則判定為冗余 Transpose 。

如果輸入也來自TransposeOp且兩個(gè) Transpose 順序?qū)е氯哂?matchAndRewrite方法會(huì)用TransposeOp的輸入替換TransposeOp。實(shí)現(xiàn) Transpose 消除。matchAndRewrite 方法首先獲取 TransposeOp 的輸入,并檢查該輸入是否也來自一個(gè) TransposeOp。如果不是, 或兩個(gè) Transpose 的順序不導(dǎo)致冗余, 則返回 failure。最后返回 success 表示成功消除冗余 Transpose 。

最終,上面介紹的2個(gè)Pass都被封裝到 AutoNhwcPass 中作用在 MLIR 的計(jì)算圖上完成全局優(yōu)化。從下面的代碼可以看到這個(gè)優(yōu)化只有在打開 ONEFLOW_MLIR_PREFER_NHWC 環(huán)境變量時(shí)才正常生效。

voidpopulateAutoNhwcPatterns(::RewritePatternSet&patterns){
boolenable_nhwc=::ParseBooleanFromEnv("ONEFLOW_MLIR_PREFER_NHWC",false);
if(enable_nhwc){
patterns.add(patterns.getContext());
patterns.add(patterns.getContext());
}
}

classAutoNhwcPass:publicAutoNhwcPassBase{
voidrunOnOperation()override{
Operation*op=getOperation();
RewritePatternSetpatterns(op->getContext());
oneflow::populateAutoNhwcPatterns(patterns);
(void)applyPatternsAndFoldGreedily(op,std::move(patterns));
}
};

補(bǔ)充:0x1.4 weight的transpose消除

這里還需要粗略的說明一下對(duì)于 weight 的 transpose 是如何處理的。在0x1.2中我們?yōu)?weight(常量constant op) 也插入了 Transpose Op,然后我們知道 weight 是常量,所以針對(duì) weight 的 Transpose Op 完全可以在編譯期折疊起來。這個(gè)過程是在 https://github.com/Oneflow-Inc/oneflow/blob/master/oneflow/ir/oneflow-translate/lib/OneFlow/MLIROneFlowTranslation.cpp#L808-L811 這里完成的,我們后面會(huì)單獨(dú)介紹一下 Constant Folding 的實(shí)現(xiàn)。

0x2. 結(jié)論

本文介紹了一下OneFlow的編譯器中的 Layerout Transform,這個(gè)技術(shù)在后來 OneFlow 版本的 Stable Diffusion 中也發(fā)揮了重要作用,提升了推理速度。在 TVM 的 Ansor 中也有類似的優(yōu)化,通過將不同的 Layerout 設(shè)定為 Op 的 strategy 進(jìn)而影響 Op 的 schedule,在搜索的時(shí)候考慮到 Layerout Transform 來獲得更大的搜索空間和更好的結(jié)果。在處理Transpose 額外開銷的方法并不是唯一的,這里只是采用了一種個(gè)人認(rèn)為比較簡(jiǎn)單的方式,讀者們?nèi)绻蓄愃菩枰梢宰杂砂l(fā)揮。





審核編輯:劉清

聲明:本文內(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)投訴

原文標(biāo)題:0x2. 結(jié)論

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

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

掃碼添加小助手

加入工程師交流群

    評(píng)論

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

    arm編譯器學(xué)習(xí)

    首先來了解一下編譯器,其通常分為三個(gè)部分:前端+優(yōu)化+后端。
    發(fā)表于 11-24 09:09 ?1062次閱讀

    SIMD計(jì)算機(jī)的優(yōu)化編譯器設(shè)計(jì)

    利用處理的相關(guān)資源,提高編譯器優(yōu)化性能和增強(qiáng)代碼可適應(yīng)性是SIMD處理優(yōu)化編譯的關(guān)鍵。該文基
    發(fā)表于 04-03 08:47 ?30次下載

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

    keil編譯器優(yōu)化選項(xiàng)針對(duì)ARM,對(duì)STM32編譯的一些優(yōu)化的問題
    發(fā)表于 02-25 14:18 ?3次下載

    C編譯器及其優(yōu)化

    本章將幫助讀者在ARM處理上編寫高效的C代碼。本章涉及的一些技術(shù)不僅適用于ARM處理,也適用于其他RISC處理。本章首先從ARM編譯器及其優(yōu)化
    發(fā)表于 10-17 17:22 ?2次下載

    關(guān)于volatile關(guān)鍵字對(duì)編譯器優(yōu)化的影響

    volatile關(guān)鍵字對(duì)編譯器優(yōu)化的影響
    的頭像 發(fā)表于 02-28 17:15 ?3248次閱讀

    編譯器優(yōu)化對(duì)函數(shù)的影響

    編譯器如gcc,可以指定不同的優(yōu)化參數(shù),在某些條件下,有些函數(shù)可能會(huì)被優(yōu)化掉。
    的頭像 發(fā)表于 06-22 14:58 ?3095次閱讀
    <b class='flag-5'>編譯器</b><b class='flag-5'>優(yōu)化</b>對(duì)函數(shù)的影響

    PyTorch教程12.1優(yōu)化深度學(xué)習(xí)

    電子發(fā)燒友網(wǎng)站提供《PyTorch教程12.1優(yōu)化深度學(xué)習(xí).pdf》資料免費(fèi)下載
    發(fā)表于 06-05 15:08 ?0次下載
    PyTorch教程12.1<b class='flag-5'>之</b><b class='flag-5'>優(yōu)化</b>和<b class='flag-5'>深度</b><b class='flag-5'>學(xué)習(xí)</b>

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

    一個(gè)程序首先要保證正確性,在保證正確性的基礎(chǔ)上,性能也是一個(gè)重要的考量。要編寫高性能的程序,第一,必須選擇合適的算法和數(shù)據(jù)結(jié)構(gòu);第二,應(yīng)該編寫編譯器能夠有效優(yōu)化以轉(zhuǎn)換成高效可執(zhí)行代碼的源代碼,要做到
    的頭像 發(fā)表于 11-24 15:37 ?1342次閱讀
    <b class='flag-5'>編譯器</b>的<b class='flag-5'>優(yōu)化</b>選項(xiàng)

    深度學(xué)習(xí)編譯器和推理引擎的區(qū)別

    深度學(xué)習(xí)編譯器和推理引擎在人工智能領(lǐng)域中都扮演著至關(guān)重要的角色,但它們各自的功能、應(yīng)用場(chǎng)景以及優(yōu)化目標(biāo)等方面存在顯著的差異。以下是對(duì)兩者區(qū)別的詳細(xì)探討。
    的頭像 發(fā)表于 07-17 18:12 ?1785次閱讀

    Keil編譯器優(yōu)化方法

    我們都知道,代碼是可以通過編譯器優(yōu)化的,有的時(shí)候,為了提高運(yùn)行速度或者減少代碼尺寸,會(huì)開啟優(yōu)化選項(xiàng)。
    的頭像 發(fā)表于 10-23 16:35 ?2028次閱讀
    Keil<b class='flag-5'>編譯器</b><b class='flag-5'>優(yōu)化</b>方法

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

    Triton編譯器與其他編譯器的比較主要體現(xiàn)在以下幾個(gè)方面: 一、定位與目標(biāo) Triton編譯器 : 定位:專注于深度學(xué)習(xí)中最核心、最耗時(shí)的
    的頭像 發(fā)表于 12-24 17:25 ?985次閱讀

    Triton編譯器支持的編程語言

    Triton編譯器支持的編程語言主要包括以下幾種: 一、主要編程語言 Python :Triton編譯器通過Python接口提供了對(duì)Triton語言和編譯器的訪問,使得用戶可以在Python環(huán)境中
    的頭像 發(fā)表于 12-24 17:33 ?949次閱讀

    Triton編譯器在機(jī)器學(xué)習(xí)中的應(yīng)用

    1. Triton編譯器概述 Triton編譯器是NVIDIA Triton推理服務(wù)平臺(tái)的一部分,它負(fù)責(zé)將深度學(xué)習(xí)模型轉(zhuǎn)換為優(yōu)化的格式,以便
    的頭像 發(fā)表于 12-24 18:13 ?975次閱讀

    Triton編譯器的優(yōu)勢(shì)與劣勢(shì)分析

    Triton編譯器作為一種新興的深度學(xué)習(xí)編譯器,具有一系列顯著的優(yōu)勢(shì),同時(shí)也存在一些潛在的劣勢(shì)。以下是對(duì)Triton編譯器優(yōu)勢(shì)與劣勢(shì)的分析:
    的頭像 發(fā)表于 12-25 09:07 ?1168次閱讀

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

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