# Licensed to the Apache Software Foundation (ASF) under one# or more contributor license agreements. See the NOTICE file# distributed with this work for additional information# regarding copyright ownership. The ASF licenses this file# to you under the Apache License, Version 2.0 (the# "License"); you may not use this file except in compliance# with the License. You may obtain a copy of the License at## http://www.apache.org/licenses/LICENSE-2.0## Unless required by applicable law or agreed to in writing,# software distributed under the License is distributed on an# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY# KIND, either express or implied. See the License for the# specific language governing permissions and limitations# under the License.# pylint: disable=invalid-name,unused-argument"""TVM operator fully connected compute."""importtvmfromtvmimporttefrom..importtag,add
[文档]defmatmul(tensor_a,tensor_b,bias=None,out_dtype=None,transpose_a=False,transpose_b=False,auto_scheduler_rewritten_layout="",meta_schedule_original_shape=None,):"""The default implementation of matmul in topi. Parameters ---------- tensor_a : tvm.te.Tensor 2-D with shape [batch, in_dim] tensor_b : tvm.te.Tensor 2-D with shape [out_dim, in_dim] bias : Optional[tvm.te.Tensor] 1-D with shape [out_dim] out_dtype : Optional[str] The output type. This is used for mixed precision. transpose_a : Optional[bool] = False Whether the tensor_a is in transposed format. transpose_b : Optional[bool] = False Whether the tensor_b is in transposed format. auto_scheduler_rewritten_layout: Optional[str] = "" The layout after auto-scheduler's layout rewrite pass. meta_schedule_original_shape: Optional[List[PrimExpr]] = None The original shape of the input tensor. Returns ------- output : tvm.te.Tensor 2-D with shape [batch, out_dim] """# TODO(yixin): support cases for 1-dim input# TODO(yixin): adding support and further check for >2-dim input in autotvm templateassert(len(tensor_a.shape)>=2andlen(tensor_b.shape)>=2),"1-dim matmul is not supported yet."ifbiasisnotNone:assertlen(bias.shape)==1ifout_dtypeisNone:out_dtype=tensor_a.dtypeiftranspose_a:reduce_dim_a,in_dim=tensor_a.shape[-2:]else:in_dim,reduce_dim_a=tensor_a.shape[-2:]batch_dims_a=tensor_a.shape[:-2]ifauto_scheduler_rewritten_layout:# Infer shape for the rewritten layoutraiseRuntimeError("LEGACY-FLOW triggered, to be removed")ifmeta_schedule_original_shape:raiseRuntimeError("LEGACY-FLOW triggered, to be removed")iftranspose_b:out_dim,reduce_dim_b=tensor_b.shape[-2:]else:reduce_dim_b,out_dim=tensor_b.shape[-2:]batch_dims_b=tensor_b.shape[:-2]ifnotisinstance(reduce_dim_a,tvm.tir.Var)andnotisinstance(reduce_dim_b,tvm.tir.Var):assertint(reduce_dim_a)==int(reduce_dim_b),f"Reduction dimensions of dense do not match. {reduce_dim_a} vs {reduce_dim_b}."result_ndim=max(len(batch_dims_a),len(batch_dims_b))batch_dims_a=[1]*(result_ndim-len(batch_dims_a))+batch_dims_abatch_dims_b=[1]*(result_ndim-len(batch_dims_b))+batch_dims_bforidx,(l,r)inenumerate(zip(batch_dims_a,batch_dims_b)):if(notisinstance(l,tvm.tir.Var)andnotisinstance(r,tvm.tir.Var)andint(l)!=1andint(r)!=1):assertint(l)==int(r),("Batch dimensions of dense do not match: "f"{tensor_a.shape[:-2]} vs {tensor_b.shape[:-2]}.")ifnotisinstance(l,tvm.tir.Var)andint(l)==1:batch_dims_a[idx]=batch_dims_b[idx]k=te.reduce_axis((0,reduce_dim_a),name="k")defcompute(*indices):batch_indices_a=indices[-len(tensor_a.shape):-2]batch_indices_a=[iifisinstance(dim,tvm.tir.Var)orint(dim)!=1else0fori,diminzip(batch_indices_a,tensor_a.shape[:-2])]batch_indices_b=indices[-len(tensor_b.shape):-2]batch_indices_b=[iifisinstance(dim,tvm.tir.Var)orint(dim)!=1else0fori,diminzip(batch_indices_b,tensor_b.shape[:-2])]i,j=indices[-2:]a_indices=(*batch_indices_a,k,i)iftranspose_aelse(*batch_indices_a,i,k)b_indices=(*batch_indices_b,j,k)iftranspose_belse(*batch_indices_b,k,j)returnte.sum(tensor_a[a_indices].astype(out_dtype)*tensor_b[b_indices].astype(out_dtype),axis=k)compute_name={(True,True):"T_matmul_TT",(True,False):"T_matmul_TN",(False,True):"T_matmul_NT",(False,False):"T_matmul_NN",}[(transpose_a,transpose_b)]# TODO(jcf94): Remove `dense` when `matmul` is finally readycompute_tag="dense"if(transpose_a,transpose_b)==(False,True)else"matmul"mat=te.compute((*batch_dims_a,in_dim,out_dim),compute,name=compute_name,tag=compute_tag,attrs={"layout_free_placeholders":[tensor_b]},)ifbiasisnotNone:mat=add(mat,bias.astype(out_dtype))ifauto_scheduler_rewritten_layout:raiseRuntimeError("LEGACY-FLOW triggered, to be removed")returnmat
[文档]defdense(data,weight,bias=None,out_dtype=None,auto_scheduler_rewritten_layout="",meta_schedule_original_shape=None,):"""The default implementation of dense in topi. This is an alias of matmul_nt operator for data tensor in non-transposed format and weight tensor in transposed format. Parameters ---------- data : tvm.te.Tensor 2-D with shape [batch, in_dim] weight : tvm.te.Tensor 2-D with shape [out_dim, in_dim] bias : Optional[tvm.te.Tensor] 1-D with shape [out_dim] out_dtype : Optional[str] The output type. This is used for mixed precision. auto_scheduler_rewritten_layout: str = "" The layout after auto-scheduler's layout rewrite pass. meta_schedule_original_shape: Optional[List[PrimExpr]] = None The original shape of the input tensor. Returns ------- output : tvm.te.Tensor 2-D with shape [batch, out_dim] """returnmatmul(data,weight,bias,out_dtype,False,True,auto_scheduler_rewritten_layout,meta_schedule_original_shape,)
[文档]defdense_pack(data,weight,bias=None,out_dtype=None):"""The default implementation of dense_pack in topi. Parameters ---------- data : tvm.te.Tensor 2-D with shape [batch, in_dim] weight : tvm.te.Tensor 2-D with shape [out_dim, in_dim] bias : Optional[tvm.te.Tensor] 1-D with shape [out_dim] out_dtype : Optional[str] The output type. This is used for mixed precision. Returns ------- output : tvm.te.Tensor 2-D with shape [batch, out_dim] """ifout_dtypeisNone:out_dtype=data.dtypeM,K=get_const_tuple(data.shape)# batch, in_dimN,_,packw_bn=get_const_tuple(weight.shape)# out_dimN=N*packw_bnidxdiv=tvm.tir.indexdividxmod=tvm.tir.indexmodk=te.reduce_axis((0,K),name="k")C=te.compute((M,N),lambday,x:te.sum(data[y,k].astype(out_dtype)*weight[idxdiv(x,packw_bn),k,idxmod(x,packw_bn)].astype(out_dtype),axis=k,),name="T_dense_pack",tag="dense_pack",)ifbiasisnotNone:C=te.compute((M,N),lambdai,j:C[i,j]+bias[j].astype(out_dtype),tag=tag.BROADCAST)returnC