Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions scripts/run_host_overhead_control.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,17 +94,18 @@ def add():

gemm_a = torch.randn((4, 48, 64), dtype=torch.float32, device=device)
gemm_b = torch.randn((4, 64, 6), dtype=torch.float32, device=device)
gemm_c = torch.empty((4, 48, 6), dtype=torch.float32, device=device)
gemm_y = torch.empty((4, 48, 6), dtype=torch.float32, device=device)

def gemm():
ops.gemm(
gemm_a,
gemm_b,
None,
1.0,
0.0,
False,
False,
gemm_c,
gemm_y,
stream=stream,
implementation_index=1,
)
Expand All @@ -125,7 +126,7 @@ def gemm():
{
"a_shape": [4, 48, 64],
"b_shape": [4, 64, 6],
"c_shape": [4, 48, 6],
"y_shape": [4, 48, 6],
"dtype": "float32",
"implementation_index": 1,
},
Expand Down
66 changes: 38 additions & 28 deletions src/base/gemm.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#define INFINI_OPS_BASE_GEMM_H_

#include <algorithm>
#include <cassert>
#include <optional>

#include "operator.h"
Expand All @@ -10,59 +11,68 @@ namespace infini::ops {

class Gemm : public Operator<Gemm> {
public:
Gemm(const Tensor a, const Tensor b, std::optional<float> alpha,
std::optional<float> beta, std::optional<int> trans_a,
std::optional<int> trans_b, Tensor c)
Gemm(const Tensor a, const Tensor b, const std::optional<Tensor> c,
std::optional<float> alpha, std::optional<float> beta,
std::optional<int> trans_a, std::optional<int> trans_b, Tensor y)
: alpha_{alpha.value_or(1.0)},
beta_{beta.value_or(1.0)},
beta_{EffectiveBeta(c, beta)},
trans_a_{static_cast<bool>(trans_a.value_or(false))},
trans_b_{static_cast<bool>(trans_b.value_or(false))},
m_{c.size(-2)},
n_{c.size(-1)},
m_{y.size(-2)},
n_{y.size(-1)},
k_{trans_a_ ? a.size(-2) : a.size(-1)},
a_type_{a.dtype()},
b_type_{b.dtype()},
c_type_{c.dtype()},
y_type_{y.dtype()},
a_strides_{a.strides()},
b_strides_{b.strides()},
c_strides_{c.strides()},
y_strides_{y.strides()},
lda_{std::max(a.stride(-2), a.stride(-1))},
ldb_{std::max(b.stride(-2), b.stride(-1))},
ldc_{std::max(c.stride(-2), c.stride(-1))},
batch_count_{c.strides().size() > 2 ? c.size(-3) : 1},
ldy_{std::max(y.stride(-2), y.stride(-1))},
batch_count_{y.strides().size() > 2 ? y.size(-3) : 1},
batch_stride_a_{a.strides().size() > 2 ? a.stride(-3) : 0},
batch_stride_b_{b.strides().size() > 2 ? b.stride(-3) : 0},
batch_stride_c_{c.strides().size() > 2 ? c.stride(-3) : 0} {
batch_stride_y_{y.strides().size() > 2 ? y.stride(-3) : 0} {
// TODO: Check constraints.
}

Gemm(const Tensor a, const Tensor b, Tensor c)
: Gemm{a, b, std::nullopt, std::nullopt, std::nullopt, std::nullopt, c} {}
Gemm(const Tensor a, const Tensor b, Tensor y)
: Gemm{a,
b,
std::nullopt,
std::nullopt,
std::nullopt,
std::nullopt,
std::nullopt,
y} {}

virtual void operator()(const Tensor a, const Tensor b,
const std::optional<Tensor> c,
std::optional<float> alpha, std::optional<float> beta,
std::optional<int> trans_a,
std::optional<int> trans_b, Tensor c) const = 0;
std::optional<int> trans_b, Tensor y) const = 0;

virtual void operator()(const Tensor a, const Tensor b, Tensor c) const {
virtual void operator()(const Tensor a, const Tensor b, Tensor y) const {
return operator()(a, b, std::nullopt, std::nullopt, std::nullopt,
std::nullopt, c);
}

virtual void operator()(const Tensor a, const Tensor b,
std::optional<float> alpha, std::optional<float> beta,
Tensor c) const {
return operator()(a, b, alpha, beta, std::nullopt, std::nullopt, c);
std::nullopt, std::nullopt, y);
}

template <typename TensorLike>
static auto MakeReturnValue(const TensorLike& a, const TensorLike& b) {
Tensor::Shape c_shape{a.shape()[a.shape().size() - 2],
Tensor::Shape y_shape{a.shape()[a.shape().size() - 2],
b.shape()[b.shape().size() - 1]};
return TensorLike::Empty(c_shape, a.dtype(), a.device());
return TensorLike::Empty(y_shape, a.dtype(), a.device());
}

protected:
static float EffectiveBeta(const std::optional<Tensor>& c,
std::optional<float> beta) {
static_cast<void>(beta);
assert(!c && "operator Gemm C input is not supported yet");
return 0.0F;
}

float alpha_{1.0};

float beta_{1.0};
Expand All @@ -81,27 +91,27 @@ class Gemm : public Operator<Gemm> {

const DataType b_type_;

const DataType c_type_;
const DataType y_type_;

Tensor::Strides a_strides_;

Tensor::Strides b_strides_;

Tensor::Strides c_strides_;
Tensor::Strides y_strides_;

Tensor::Stride lda_{0};

Tensor::Stride ldb_{0};

Tensor::Stride ldc_{0};
Tensor::Stride ldy_{0};

Tensor::Size batch_count_{1};

Tensor::Stride batch_stride_a_{0};

Tensor::Stride batch_stride_b_{0};

Tensor::Stride batch_stride_c_{0};
Tensor::Stride batch_stride_y_{0};
};

} // namespace infini::ops
Expand Down
42 changes: 28 additions & 14 deletions src/native/ascend/ops/gemm/kernel.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,21 +15,33 @@ namespace infini::ops {
template <>
class Operator<Gemm, Device::Type::kAscend> : public Gemm {
public:
Operator(const Tensor a, const Tensor b, std::optional<float> alpha,
std::optional<float> beta, std::optional<int> trans_a,
std::optional<int> trans_b, Tensor c)
: Gemm(a, b, alpha, beta, trans_a, trans_b, c),
Operator(const Tensor a, const Tensor b, const std::optional<Tensor> c,
std::optional<float> alpha, std::optional<float> beta,
std::optional<int> trans_a, std::optional<int> trans_b, Tensor y)
: Gemm(a, b, c, alpha, beta, trans_a, trans_b, y),
batched_{batch_count_ > 1},
alpha_val_{alpha.value_or(1.0f)},
beta_val_{beta.value_or(1.0f)},
self_cache_(c),
beta_val_{0.0f},
self_cache_(y),
a_cache_(a, trans_a_),
b_cache_(b, trans_b_),
out_cache_(c) {
out_cache_(y) {
alpha_scalar_ = aclCreateScalar(&alpha_val_, ACL_FLOAT);
beta_scalar_ = aclCreateScalar(&beta_val_, ACL_FLOAT);
}

Operator(const Tensor a, const Tensor b, Tensor y)
: Operator{a,
b,
std::nullopt,
std::nullopt,
std::nullopt,
std::nullopt,
std::nullopt,
y} {}

using Gemm::operator();

~Operator() {
if (!ascend::IsAclRuntimeAlive()) return;

Expand All @@ -43,15 +55,17 @@ class Operator<Gemm, Device::Type::kAscend> : public Gemm {
if (beta_scalar_) aclDestroyScalar(beta_scalar_);
}

void operator()(const Tensor a, const Tensor b, std::optional<float> alpha,
std::optional<float> beta, std::optional<int> trans_a,
std::optional<int> trans_b, Tensor c) const override {
void operator()(const Tensor a, const Tensor b, const std::optional<Tensor> c,
std::optional<float> alpha, std::optional<float> beta,
std::optional<int> trans_a, std::optional<int> trans_b,
Tensor y) const override {
static_cast<void>(EffectiveBeta(c, beta));
auto stream = static_cast<aclrtStream>(stream_);

auto t_self = self_cache_.get(c.data());
auto t_self = self_cache_.get(y.data());
auto t_a = a_cache_.get(const_cast<void*>(a.data()));
auto t_b = b_cache_.get(const_cast<void*>(b.data()));
auto t_out = out_cache_.get(c.data());
auto t_out = out_cache_.get(y.data());

if (!executor_) {
if (batched_) {
Expand All @@ -65,10 +79,10 @@ class Operator<Gemm, Device::Type::kAscend> : public Gemm {
}
aclSetAclOpExecutorRepeatable(executor_);
} else {
aclSetInputTensorAddr(executor_, 0, t_self, c.data());
aclSetInputTensorAddr(executor_, 0, t_self, y.data());
aclSetInputTensorAddr(executor_, 1, t_a, const_cast<void*>(a.data()));
aclSetInputTensorAddr(executor_, 2, t_b, const_cast<void*>(b.data()));
aclSetOutputTensorAddr(executor_, 0, t_out, c.data());
aclSetOutputTensorAddr(executor_, 0, t_out, y.data());
}

auto& arena = ascend::GetWorkspacePool().Ensure(stream, ws_size_);
Expand Down
53 changes: 29 additions & 24 deletions src/native/cambricon/ops/gemm/cnblas.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,24 +18,24 @@ namespace infini::ops {
template <>
class Operator<Gemm, Device::Type::kCambricon> : public Gemm {
public:
Operator(const Tensor a, const Tensor b, std::optional<float> alpha,
std::optional<float> beta, std::optional<int> trans_a,
std::optional<int> trans_b, Tensor c)
: Gemm{a, b, alpha, beta, trans_a, trans_b, c},
Operator(const Tensor a, const Tensor b, const std::optional<Tensor> c,
std::optional<float> alpha, std::optional<float> beta,
std::optional<int> trans_a, std::optional<int> trans_b, Tensor y)
: Gemm{a, b, c, alpha, beta, trans_a, trans_b, y},
a_rows_{a.size(-2)},
a_cols_{a.size(-1)},
b_rows_{b.size(-2)},
b_cols_{b.size(-1)},
c_rows_{c.size(-2)},
c_cols_{c.size(-1)} {
y_rows_{y.size(-2)},
y_cols_{y.size(-1)} {
assert(!trans_a_ && "`trans_a` is not currently supported");
assert(!trans_b_ && "`trans_b` is not currently supported");

cnnlCreate(&cnnl_handle_);

cnnlCreateTensorDescriptor(&desc_a_);
cnnlCreateTensorDescriptor(&desc_b_);
cnnlCreateTensorDescriptor(&desc_c_);
cnnlCreateTensorDescriptor(&desc_y_);

cnnlCreateMatMulDescriptor(&matmul_desc_);
cnnlCreateMatMulAlgo(&matmul_algo_);
Expand All @@ -49,27 +49,31 @@ class Operator<Gemm, Device::Type::kCambricon> : public Gemm {
batch_count_, batch_stride_a_);
SetupTensorDescriptor(desc_b_, b_strides_, b_type_, b_rows_, b_cols_,
batch_count_, batch_stride_b_);
SetupTensorDescriptor(desc_c_, c_strides_, c_type_, c_rows_, c_cols_,
batch_count_, batch_stride_c_);
SetupTensorDescriptor(desc_y_, y_strides_, y_type_, y_rows_, y_cols_,
batch_count_, batch_stride_y_);
int count = 0;
cnnlGetBatchMatMulExAlgoHeuristic(cnnl_handle_, matmul_desc_, desc_a_,
desc_b_, desc_c_, NULL, 1,
desc_b_, desc_y_, NULL, 1,
&heuristic_result_, &count);

cnrtMalloc(&default_workspace_, workspace_size_in_bytes());
}

Operator(const Tensor a, const Tensor b, Tensor c)
: Operator{a, b, std::nullopt, std::nullopt, std::nullopt, std::nullopt,
c} {}
Operator(const Tensor a, const Tensor b, Tensor y)
: Operator{a,
b,
std::nullopt,
std::nullopt,
std::nullopt,
std::nullopt,
std::nullopt,
y} {}

Operator(const Tensor a, const Tensor b, std::optional<float> alpha,
std::optional<float> beta, Tensor c)
: Operator{a, b, alpha, beta, std::nullopt, std::nullopt, c} {}
using Gemm::operator();

~Operator() {
cnrtFree(default_workspace_);
cnnlDestroyTensorDescriptor(desc_c_);
cnnlDestroyTensorDescriptor(desc_y_);
cnnlDestroyTensorDescriptor(desc_b_);
cnnlDestroyTensorDescriptor(desc_a_);
cnnlDestroyMatMulDescriptor(matmul_desc_);
Expand All @@ -78,11 +82,12 @@ class Operator<Gemm, Device::Type::kCambricon> : public Gemm {
cnnlDestroy(cnnl_handle_);
}

void operator()(const Tensor a, const Tensor b, std::optional<float> alpha,
std::optional<float> beta, std::optional<int> trans_a,
std::optional<int> trans_b, Tensor c) const override {
void operator()(const Tensor a, const Tensor b, const std::optional<Tensor> c,
std::optional<float> alpha, std::optional<float> beta,
std::optional<int> trans_a, std::optional<int> trans_b,
Tensor y) const override {
const auto& alpha_value{alpha.value_or(alpha_)};
const auto& beta_value{beta.value_or(beta_)};
const auto beta_value{EffectiveBeta(c, beta)};

cnnlSetQueue(cnnl_handle_, (cnrtQueue_t)stream_);

Expand All @@ -92,7 +97,7 @@ class Operator<Gemm, Device::Type::kCambricon> : public Gemm {

cnnlBatchMatMulEx(cnnl_handle_, matmul_desc_, matmul_algo_, &alpha_value,
desc_a_, a.data(), desc_b_, b.data(), &beta_value,
desc_c_, c.data(), workspace, workspace_size);
desc_y_, y.data(), workspace, workspace_size);
}

std::size_t workspace_size_in_bytes() const override {
Expand Down Expand Up @@ -135,7 +140,7 @@ class Operator<Gemm, Device::Type::kCambricon> : public Gemm {

cnnlTensorDescriptor_t desc_b_;

cnnlTensorDescriptor_t desc_c_;
cnnlTensorDescriptor_t desc_y_;

cnnlMatMulDescriptor_t matmul_desc_;

Expand All @@ -147,7 +152,7 @@ class Operator<Gemm, Device::Type::kCambricon> : public Gemm {

Tensor::Size b_rows_, b_cols_;

Tensor::Size c_rows_, c_cols_;
Tensor::Size y_rows_, y_cols_;

// TODO: Remove the following member after default workspace mechanism has
// been introduced globally.
Expand Down
Loading
Loading