国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

腳本之家,腳本語言編程技術及教程分享平臺!
分類導航

Python|VBS|Ruby|Lua|perl|VBA|Golang|PowerShell|Erlang|autoit|Dos|bat|

服務器之家 - 腳本之家 - Python - Pytorch-mlu 實現添加逐層算子方法詳解

Pytorch-mlu 實現添加逐層算子方法詳解

2022-03-08 00:24極智視界 Python

本文主要分享了在寒武紀設備上 pytorch-mlu 中添加逐層算子的方法教程,代碼具有一定學習價值,有需要的朋友可以借鑒參考下,希望能夠有所幫助

本教程分享了在寒武紀設備上 pytorch-mlu 中添加逐層算子的方法。

pytorch-mlu 逐層模式中算子間數據傳遞和存儲的基本單元是 tensor。pytorch-mlu 根據 tensor 中的 device 屬性值將算子分發到不同設備。以 abs() 算子為例,在 dispatch 階段會根據 input_tensor 的設備屬性值將算子調用分發到具體設備,邏輯如下圖所示:

Pytorch-mlu 實現添加逐層算子方法詳解

Catch 通過注冊添加 MLU 算子方式與 pytorch 源碼解耦,下面介紹在 Catch 中添加 MLU 算子的具體步驟。

 

1、注冊算子

在 catch/torch_mlu/csrc/generated/aten_mlu_type_default.cpp 中注冊算子:

.op(torch::RegisterOperators::options().schema("aten::add.Tensor(Tensor self, Tensor other, *, Scalar alpha=1) -> Tensor")  // NOLINT 

.impl_unboxedOnlyKernel<at::Tensor(const at::Tensor &, const at::Tensor &, at::Scalar), &AtenMluType::add>(at::TensorTypeId::MLUTensorId)

aliasAnalysis(c10::AliasAnalysisKind::FROM_SCHEMA))

 

2、算子分發

AtenMluType 和 AtenMluCustomType 是 Catch 模塊中算子的入口。AtenMluType 類主要包含框架中的標準算子;而 AtenMluCustomType 類包含客制化的算子。根據算子屬性選擇在 AtenMluType 還是 AtenMluCustomType 中添加相應算子聲明和實現。

標準算子分發

在 catch/torch_mlu/csrc/aten/aten_mlu_type.h 和 catch/torch_mlu/csrc/aten/aten_mlu_type.cpp 中添加算子聲明和實現:

aten_mlu_type.h
static at::Tensor add(const at::Tensor& self, const at::Tensor& other, at::Scalar alpha);
aten_mlu_type.cpp
at::Tensor AtenMluType::add(const at::Tensor& self, const at::Tensor& other, at::Scalar alpha){
return OP_DISPATCH(add, self, other, alpha);
}

客制化算子分發

對于 MLU 特有算子,在 catch/torch_mlu/csrc/aten/aten_mlu_type.h和 catch/torch_mlu/csrc/aten/aten_mlu_custom_type.cpp 中添加算子申明和實現:

aten_mlu_type.h
static at::Tensor linear(const at::Tensor& input,
                       const at::Tensor& weight,
                       const at::Tensor& bias,
                       const at::Tensor& q_scale,
                       const at::Tensor& q_mode);
aten_mlu_custom_type.cpp
at::Tensor AtenMluCustomType::linear(const at::Tensor& input,
                                   const at::Tensor& weight,
                                   const at::Tensor& bias,
                                   const at::Tensor& q_scale,
                                   const at::Tensor& q_mode){
  return OP_DISPATCH(linear, input, weight, bias, q_scale, q_mode);
}

 

3、修改 OpMethods 基類

從 AtenMluType 和 AtenMluCustomType 中都會通過 OpMethods 下發到推理算子或訓練算子。在 catch/torch_mlu/csrc/aten/operators/op_methods.h 和 catch/torch_mlu/csrc/aten/operators/op_methods.cpp 中添加算子申明和實現。OpMethods 中的實現部分為該算子的 CPU 實現。

op_methods.h
virtual at::Tensor add(const at::Tensor& self, const at::Tensor& other, at::Scalar alpha);
op_methods.cpp
at::Tensor OpMethods::add(const at::Tensor& self,
                        const at::Tensor& other,
                        at::Scalar alpha){
 auto input_cpu = self.cpu();
 auto other_cpu = other.cpu();
 auto output = at::add(input_cpu, other_cpu, alpha);
 return output.to(at::Device(at::Device::Type::MLU));
}

 

4、下發算子

在 catch/torch_mlu/csrc/aten/operators/cnml_ops.h 和 catch/torch_mlu/csrc/aten/operators/cnml_ops.cpp 中添加推理算子申明和實現。

cnml_ops.h
at::Tensor add(const at::Tensor& self, const at::Tensor& other, at::Scalar alpha);
cnml_ops.cpp
at::Tensor CnmlOps::add(const at::Tensor& self, const at::Tensor& other, at::Scalar alpha){
CNML_DISPATCH(add, cnml_add, self, other, alpha);  // CNML_DISPATCH 宏第一個參數是該接口名,第二個參數是wrapper個名字,其余
}

 

5、添加 wrapper

wrapper 是對算子 kernel 的封裝,每個算子對應一個 wrapper。這里以 add 算子為例,添加 wrapper 如下所示:

cnml_kernel.h
at::Tensor cnml_add(const at::Tensor& input, const at::Tensor& other, at::Scalar alpha);
add.cpp
at::Tensor cnml_add(const at::Tensor& input, const at::Tensor& other, at::Scalar alpha_scalar){
TORCH_CHECK(input.dim() >= 0 || other.dim() >= 0, "dimension not support");
at::Tensor input_ = input;
at::Tensor other_ = other;
auto alpha_data = alpha_scalar.to<scalar_t>();
if(alpha_data != 1){
  // scale_t
  other_ = cnml::ops::cnml_scale(other_, alpha_data, 0);
}
if(other_.dim() < 1 && other_.device().type() == c10::DeviceType::CPU){
  auto other_scalar = other_.item();
  return cnml_add_internal(input_, other_scalar);   // 調用kernel
}
if(input_.dim() < 1 && input_.device().type() == c10::DeviceType::CPU){
  auto input_scalar = input_.item();
  return cnml_add_internal(other_, input_scalar);   // 調用 kernel
}

bool broadcast = input_.sizes() != other_.sizes();
if(broadcast){
  auto broadcast_size = at::infer_size(input.sizes(), other.sizes());
  at::Tensor broadcast1 = cnml::ops::cnml_expand(input_, broadcast_size, false);
  at::Tensor broadcast2 = cnml::ops::cnml_expand(other_, broadcast_size, false);
  return cnml_add_internal(broadcast1, broadcast2);  // 調用 kernel
}else{
  return cnml_add_internal(input_, other_);  //調用 kernel
}
return cnml_add_internal(input_, other_);   //調用 kernel
}

 

6、添加 wrapper

Wrapper 中通過調用 kernel 實現算子功能。示例中調用的是 cnml_add_internal。算子的具體實現主要通過調用 CNML 庫的接口來完成,下面是 CNML 庫的邏輯:

Pytorch-mlu 實現添加逐層算子方法詳解

kernel 實現就是按照上述編程邏輯調用 CNML 庫接口完成的,在 catch/torch_mlu/csrc/aten/operators/cnml/internal/cnml_internal.h 和 catch/torch_mlu/csrc/aten/operators/cnml/internal/add_internal/cpp 中添加 kernel 函數的聲明和實現。

cnml_internal.h
at::Tensor cnml_add_internal(const at::Tensor& input1, const at::Tensor& input2);
add_internal.cpp
at::Tensor cnml_add_internal(const at::Tensor& input1, const at::Tensor& input2){
auto output = at::native::empty_like(input1);
// prepare input cnml tensor
auto* input1_impl = getMluTensorImpl(input1);  // 獲取MluTensorImpl
auto input1_cnml = input1_impl->CreateCnmlTensor(
     CNML_TENSOR, toCnmlDataType(input1.dtype()));  // 類型自適應:toCnmlDataType()
     
auto* input2_impl = getMluTensorImpl(input2);
auto input2_cnml = input2_impl->CreateCnmlTensor(
    CNML_TENSOR, toCnmlDataType(input2.dtype()));
    
// prepare output cnml tensor
auto* output_impl = getMluTensorImpl(output);
auto output_cnml = output_impl->CreateCnmlTensor(
    CNML_TENSOR, toCnmlDataType(output.dtype()));
    
// End the execution flow if not MLU device
CHECK_MLU_DEVICE(output);

// setup operator
cnmlBaseOp_t add_op;
TORCH_CNML_CHECK(cnmlCreateAddOp(&add_op, input1_cnml, input2_cnml, output_cnml));

// return to JIT if running mode is fuse
CHEXK_RETURN_TO_FUSE(add_op, output);

// compile op
TORCH_CNML_CHECK(cnmlCompileBaseOp(add_op, GET_CORE_VERSION, GET_CORE_NUMBER));

auto queue = getCurQueue();
TORCH_CNML_CHECK(cnmlComputeAddOpForward_V4(add_op,
                                            NULL,
                                            input1_impl->raw_mutable_data(),
                                            NULL,
                                            input2_impl->raw_mutable_data(),
                                            NULL,
                                            output_impl->raw_mutable_data(),
                                            queue,
                                            NULL));
 syncQueue(queue);
 TORCH_CNML_CHECK(cnmlDestroyBaseOp(&add_op));
 
return output;
}

對 MLU 不支持算子的處理

對于 MLU 暫不支持的操作,輸入數據將會拷貝到 CPU 上,然后調用 CPU 相關操作,使其在 CPU 上運行,最后再將輸出結果拷會到 MLU 上。具體實現,可以查詢 op_methods.cp,該文件在 catch/torch_mlu/csrc/aten/operators/ 目錄下。

op_methods.cpp
at::Tensor OpMethods::add(const at::Tensor& self,
                        const at::Tensor& other,
                        at::Scalar alpha){
auto input_cpu = self.cpu();
auto other_cpu = other.cpu();
auto output = at::add(input_cpu, other_cpu, alpha);
return output.to(at::Device(at::Device::Type::MLU));
}

對于新增的算子在執行過程中拋出異常時,如果 CPU 上沒有對應的算子操作,那么該操作無法切換到 CPU 上運行;

Wrapper一般以 cnml_算子名命名,kernel一般以cnml_算子名_internal命名

 

7、算子測試

使用基于 python 的 unittest 模塊編寫算子單元測試。測試時需提供相同的參數和輸入數據,分別在 MLU 和 CPU 上執行算子,對比兩者的輸出結果。MLU 和 CPU 計算結果可能會有差異,一般情況下兩者的相對誤差在 2% 以內均是可以接受的。

def test_add(self):
# "Tensor + Tensor" mode testing
for shape1, shape2 in [((1,3,224,224),(1,3,224,224)),((2,30,80),(2,30,80)),((3,20),(3,20)),((10),(10))]:
  input1_cpu = torch.rand(shape1, dtype=torch.float)
  input2_cpu = torch.rand(shape2, dtype=torch.float)
  input1_mlu = input1_cpu.to(xm.mlu_device())
  input2_mlu = input2_cpu.to(xm.mlu_device())
  # 在 CPU 上計算
  output_cpu = input1_cpu + input2_cpu
  # 在 MLU 上計算
  output_mlu = input1_mlu + input2_mlu
  # 計算 MLU 的誤差,并確保相對誤差在 2% 以內
  self.assertTensorsEqual(output_cpu, output_mlu.cpu(), 0.02, use_MSE=True) 

 以上分享了在寒武紀設備 pytorch-mlu 中添加逐層算子的方法,并以 add() 算子為例進行了示例編寫,希望我的分享會對你的學習有一點幫助。

到此這篇關于Pytorch-mlu 實現添加逐層算子方法詳解的文章就介紹到這了,更多相關Pytorch內容請搜索服務器之家以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持服務器之家!

原文鏈接:https://blog.csdn.net/weixin_42405819/article/details/121520614

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: av影音 | 成年人视频在线观看免费 | 欧洲毛片 | av在线电影网 | 欧美高清一区 | 91中文在线 | 在线观看欧美日韩 | 亚洲高清av | 国产美女一区二区三区 | 黄片毛片在线 | 国产精品99一区二区三区 | 日韩中文字幕免费在线播放 | 久久中文字幕在线 | 成人av播放 | 一级片免费视频 | 久久久久久亚洲精品中文字幕 | 成人综合免费视频 | 午夜激情影院 | 日韩中文字幕在线播放 | 中文字幕一区在线观看视频 | 综合网伊人 | 亚洲视频综合 | 中文字幕成人 | 中文字幕亚洲一区二区va在线 | 国产黄色电影 | 欧美激情一区二区 | 亚洲国产精品久久久久秋霞蜜臀 | 午夜影院免费 | 国产麻豆乱码精品一区二区三区 | 在线视频 亚洲 | 91在线免费视频 | 青青青国产精品一区二区 | 国产在线精品一区二区 | 成人aaaa免费全部观看 | 日韩在线 | 亚洲国产精品久久 | 日日操操 | 国产成人精品亚洲日本在线观看 | 成人网在线看 | 97精品超碰一区二区三区 | 免费成人黄色 |