blob: a14ca7ac36d7303b2d6c19ed1fbdde0edbb31efc [file]
# 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.
from __future__ import annotations
import tempfile
from tvm import relax, runtime
import tvm
import tvm.testing
from tvm import relax
import scipy
from scipy.special import erf
import numpy as np
from tvm.target import Target
from tvm.relax.vm_build import build as relax_build
from tvm.script.ir_builder import relax as R
from tvm.script.ir_builder import ir as I
from tvm.script.ir_builder import tir as T
from tvm.script.ir_builder import IRBuilder
from tvm.relax.backend_tir import get_tir_pattern
from tvm.relax.backend_tir.contrib.cutlass import cutlass_fcodegen, compile_options
A_TYPE = "float16"
B_TYPE = "float16"
C_TYPE = "float16"
target = Target("cuda")
def f_run(rt_mod: runtime.Module, device: runtime.ndarray.Device, *input):
vm = relax.vm.VirtualMachine(rt_mod=rt_mod, device=device)
return vm["main"](*input)
def build(mod):
mod = relax.transform.LegalizeOps()(mod)
mod = relax.transform.AnnotateTIROpPattern()(mod)
mod = relax.transform.FuseOps()(mod)
mod = relax.transform.FuseTIR()(mod)
mod = relax.transform.SplitCallTIRByPattern(get_tir_pattern(), cutlass_fcodegen())(mod)
mod = relax.transform.DeadCodeElimination()(mod)
print(mod.script())
f = tempfile.NamedTemporaryFile(suffix=".so", delete=True)
executable = relax_build(mod, target)
executable.mod.export_library(f.name, **compile_options(target))
rt_mod = runtime.load_module(f.name)
f.close()
return rt_mod
def build_and_run_reference(mod, inputs_np):
dev = tvm.device("llvm", 0)
ex = relax.build(mod, "llvm")
vm = relax.VirtualMachine(ex, dev)
f = vm["main"]
inputs = [tvm.nd.array(inp, dev) for inp in inputs_np]
return f(*inputs).numpy()
def constructGEMM(M, N, K):
with IRBuilder() as ib: # pylint: disable=invalid-name
with I.ir_module() as frame:
with R.function():
R.func_name("main")
A = R.arg(
"A", relax.TensorStructInfo((M, K), A_TYPE)
) # pylint: disable=invalid-name
B = R.arg(
"B", relax.TensorStructInfo((K, N), B_TYPE)
) # pylint: disable=invalid-name
with R.dataflow() as df:
C = R.emit(R.matmul(A, B, out_dtype=C_TYPE))
R.output(C)
(C,) = df.output_vars
R.func_ret_value(C)
relax_mod = ib.get()
return relax_mod
@tvm.testing.requires_cutlass
def test_cutlass_dense():
m, n, k = 128, 64, 256
executable = build(constructGEMM(m, n, k))
dev = tvm.cuda()
A = np.random.randn(m, k).astype("float16")
B = np.random.randn(k, n).astype("float16")
A_tvm = tvm.nd.array(A, dev)
B_tvm = tvm.nd.array(B, dev)
result = f_run(executable, dev, A_tvm, B_tvm)
np.testing.assert_allclose(result.numpy(), A @ B, rtol=5e-2, atol=5e-2)
def constructGEMM_bias(M, N, K):
with IRBuilder() as ib: # pylint: disable=invalid-name
with I.ir_module() as frame:
with R.function():
R.func_name("main")
A = R.arg(
"A", relax.TensorStructInfo((M, K), A_TYPE)
) # pylint: disable=invalid-name
B = R.arg(
"B", relax.TensorStructInfo((K, N), B_TYPE)
) # pylint: disable=invalid-name
bias = R.arg(
"bias", relax.TensorStructInfo((1, N), A_TYPE)
) # pylint: disable=invalid-name
with R.dataflow() as df:
C = R.emit(R.matmul(A, B, out_dtype=C_TYPE))
D = R.emit(R.add(C, bias))
R.output(D)
(D,) = df.output_vars
R.func_ret_value(D)
relax_mod = ib.get()
return relax_mod
def constructGEMM_bias2(M, N, K):
with IRBuilder() as ib: # pylint: disable=invalid-name
with I.ir_module() as frame:
with R.function():
R.func_name("main")
A = R.arg(
"A", relax.TensorStructInfo((M, K), A_TYPE)
) # pylint: disable=invalid-name
B = R.arg(
"B", relax.TensorStructInfo((K, N), B_TYPE)
) # pylint: disable=invalid-name
bias = R.arg(
"bias", relax.TensorStructInfo((N,), A_TYPE)
) # pylint: disable=invalid-name
with R.dataflow() as df:
C = R.emit(R.matmul(A, B, out_dtype=C_TYPE))
D = R.emit(R.add(C, bias))
R.output(D)
(D,) = df.output_vars
R.func_ret_value(D)
relax_mod = ib.get()
return relax_mod
@tvm.testing.requires_cutlass
def test_cutlass_dense_bias():
m, n, k = 128, 64, 256
executable = build(constructGEMM_bias(m, n, k))
dev = tvm.cuda()
A = np.random.randn(m, k).astype("float16")
B = np.random.randn(k, n).astype("float16")
bias = np.random.randn(1, n).astype("float16")
A_tvm = tvm.nd.array(A, dev)
B_tvm = tvm.nd.array(B, dev)
bias_tvm = tvm.nd.array(bias, dev)
result = f_run(executable, dev, A_tvm, B_tvm, bias_tvm)
np.testing.assert_allclose(result.numpy(), A @ B + bias, rtol=5e-2, atol=5e-2)
@tvm.testing.requires_cutlass
def test_cutlass_dense_bias2():
m, n, k = 128, 64, 256
executable = build(constructGEMM_bias2(m, n, k))
dev = tvm.cuda()
A = np.random.randn(m, k).astype("float16")
B = np.random.randn(k, n).astype("float16")
bias = np.random.randn(n).astype("float16")
A_tvm = tvm.nd.array(A, dev)
B_tvm = tvm.nd.array(B, dev)
bias_tvm = tvm.nd.array(bias, dev)
result = f_run(executable, dev, A_tvm, B_tvm, bias_tvm)
np.testing.assert_allclose(result.numpy(), A @ B + bias, rtol=5e-2, atol=5e-2)
def constructGEMM_bias_relu(M, N, K):
with IRBuilder() as ib: # pylint: disable=invalid-name
with I.ir_module() as frame:
with R.function():
R.func_name("main")
A = R.arg(
"A", relax.TensorStructInfo((M, K), A_TYPE)
) # pylint: disable=invalid-name
B = R.arg(
"B", relax.TensorStructInfo((K, N), B_TYPE)
) # pylint: disable=invalid-name
bias = R.arg(
"bias", relax.TensorStructInfo((1, N), A_TYPE)
) # pylint: disable=invalid-name
with R.dataflow() as df:
C = R.emit(R.matmul(A, B, out_dtype=C_TYPE))
D = R.emit(R.add(C, bias))
E = R.emit(R.nn.relu(D))
R.output(E)
(E,) = df.output_vars
R.func_ret_value(E)
relax_mod = ib.get()
return relax_mod
@tvm.testing.requires_cutlass
def test_cutlass_dense_bias_relu():
m, n, k = 128, 64, 256
executable = build(constructGEMM_bias_relu(m, n, k))
dev = tvm.cuda()
A = np.random.randn(m, k).astype("float16")
B = np.random.randn(k, n).astype("float16")
bias = np.random.randn(1, n).astype("float16")
A_tvm = tvm.nd.array(A, dev)
B_tvm = tvm.nd.array(B, dev)
bias_tvm = tvm.nd.array(bias, dev)
result = f_run(executable, dev, A_tvm, B_tvm, bias_tvm)
np.testing.assert_allclose(result.numpy(), np.maximum(A @ B + bias, 0), rtol=5e-2, atol=5e-2)
def constructBatchGEMM(batch, M, N, K):
with IRBuilder() as ib: # pylint: disable=invalid-name
with I.ir_module() as frame:
with R.function():
R.func_name("main")
A = R.arg(
"A", relax.TensorStructInfo((batch, M, K), A_TYPE)
) # pylint: disable=invalid-name
B = R.arg(
"B", relax.TensorStructInfo((K, N), B_TYPE)
) # pylint: disable=invalid-name
with R.dataflow() as df:
C = R.emit(R.matmul(A, B, out_dtype=C_TYPE))
R.output(C)
(C,) = df.output_vars
R.func_ret_value(C)
relax_mod = ib.get()
return relax_mod
@tvm.testing.requires_cutlass
def test_cutlass_batch_dense():
b, m, n, k = 2, 128, 256, 64
executable = build(constructBatchGEMM(b, m, n, k))
dev = tvm.cuda()
A = np.random.randn(b, m, k).astype("float16")
B = np.random.randn(k, n).astype("float16")
A_tvm = tvm.nd.array(A, dev)
B_tvm = tvm.nd.array(B, dev)
result = f_run(executable, dev, A_tvm, B_tvm)
np.testing.assert_allclose(result.numpy(), A @ B, rtol=5e-2, atol=5e-2)
def constructBatchGEMM2(batch, M, N, K):
with IRBuilder() as ib: # pylint: disable=invalid-name
with I.ir_module() as frame:
with R.function():
R.func_name("main")
A = R.arg(
"A", relax.TensorStructInfo((batch, M, K), A_TYPE)
) # pylint: disable=invalid-name
B = R.arg(
"B", relax.TensorStructInfo((batch, K, N), B_TYPE)
) # pylint: disable=invalid-name
with R.dataflow() as df:
C = R.emit(R.matmul(A, B, out_dtype=C_TYPE))
R.output(C)
(C,) = df.output_vars
R.func_ret_value(C)
relax_mod = ib.get()
return relax_mod
@tvm.testing.requires_cutlass
def test_cutlass_batch_dense2():
b, m, n, k = 2, 128, 256, 64
executable = build(constructBatchGEMM2(b, m, n, k))
dev = tvm.cuda()
A = np.random.randn(b, m, k).astype("float16")
B = np.random.randn(b, k, n).astype("float16")
A_tvm = tvm.nd.array(A, dev)
B_tvm = tvm.nd.array(B, dev)
result = f_run(executable, dev, A_tvm, B_tvm)
np.testing.assert_allclose(result.numpy(), A @ B, rtol=5e-2, atol=5e-2)
def constructBatchGEMM_bias(batch, M, N, K):
with IRBuilder() as ib: # pylint: disable=invalid-name
with I.ir_module() as frame:
with R.function():
R.func_name("main")
A = R.arg(
"A", relax.TensorStructInfo((batch, M, K), A_TYPE)
) # pylint: disable=invalid-name
B = R.arg(
"B", relax.TensorStructInfo((K, N), B_TYPE)
) # pylint: disable=invalid-name
bias = R.arg(
"bias", relax.TensorStructInfo((1, N), A_TYPE)
) # pylint: disable=invalid-name
with R.dataflow() as df:
C = R.emit(R.matmul(A, B, out_dtype=C_TYPE))
D = R.emit(R.add(C, bias))
R.output(D)
(D,) = df.output_vars
R.func_ret_value(D)
relax_mod = ib.get()
return relax_mod
@tvm.testing.requires_cutlass
def test_cutlass_batch_dense_bias():
b, m, n, k = 2, 128, 256, 64
executable = build(constructBatchGEMM_bias(b, m, n, k))
dev = tvm.cuda()
A = np.random.randn(b, m, k).astype("float16")
B = np.random.randn(k, n).astype("float16")
bias = np.random.randn(1, n).astype("float16")
A_tvm = tvm.nd.array(A, dev)
B_tvm = tvm.nd.array(B, dev)
bias_tvm = tvm.nd.array(bias, dev)
result = f_run(executable, dev, A_tvm, B_tvm, bias_tvm)
np.testing.assert_allclose(result.numpy(), A @ B + bias, rtol=5e-2, atol=5e-2)
def constructBatchGEMM_bias2(batch, M, N, K):
with IRBuilder() as ib: # pylint: disable=invalid-name
with I.ir_module() as frame:
with R.function():
R.func_name("main")
A = R.arg(
"A", relax.TensorStructInfo((batch, M, K), A_TYPE)
) # pylint: disable=invalid-name
B = R.arg(
"B", relax.TensorStructInfo((K, N), B_TYPE)
) # pylint: disable=invalid-name
bias = R.arg(
"bias", relax.TensorStructInfo((N,), A_TYPE)
) # pylint: disable=invalid-name
with R.dataflow() as df:
C = R.emit(R.matmul(A, B, out_dtype=C_TYPE))
D = R.emit(R.add(C, bias))
R.output(D)
(D,) = df.output_vars
R.func_ret_value(D)
relax_mod = ib.get()
return relax_mod
@tvm.testing.requires_cutlass
def test_cutlass_batch_dense_bias2():
b, m, n, k = 2, 128, 256, 64
executable = build(constructBatchGEMM_bias2(b, m, n, k))
dev = tvm.cuda()
A = np.random.randn(b, m, k).astype("float16")
B = np.random.randn(k, n).astype("float16")
bias = np.random.randn(n).astype("float16")
A_tvm = tvm.nd.array(A, dev)
B_tvm = tvm.nd.array(B, dev)
bias_tvm = tvm.nd.array(bias, dev)
result = f_run(executable, dev, A_tvm, B_tvm, bias_tvm)
np.testing.assert_allclose(result.numpy(), A @ B + bias, rtol=5e-2, atol=5e-2)
def constructBatchGEMM_bias2_gelu(batch, M, N, K):
with IRBuilder() as ib: # pylint: disable=invalid-name
with I.ir_module() as frame:
with R.function():
R.func_name("main")
A = R.arg(
"A", relax.TensorStructInfo((batch, M, K), A_TYPE)
) # pylint: disable=invalid-name
B = R.arg(
"B", relax.TensorStructInfo((K, N), B_TYPE)
) # pylint: disable=invalid-name
bias = R.arg(
"bias", relax.TensorStructInfo((N,), A_TYPE)
) # pylint: disable=invalid-name
with R.dataflow() as df:
C = R.emit(R.matmul(A, B, out_dtype=C_TYPE))
D = R.emit(R.add(C, bias))
E = R.emit(R.nn.gelu(D))
R.output(E)
(E,) = df.output_vars
R.func_ret_value(E)
relax_mod = ib.get()
return relax_mod
@tvm.testing.requires_cutlass
def test_cutlass_batch_dense_bias2_gelu():
b, m, n, k = 2, 128, 64, 256
executable = build(constructBatchGEMM_bias2_gelu(b, m, n, k))
dev = tvm.cuda()
A = np.random.randn(b, m, k).astype("float16")
B = np.random.randn(k, n).astype("float16")
bias = np.random.randn(n).astype("float16")
A_tvm = tvm.nd.array(A, dev)
B_tvm = tvm.nd.array(B, dev)
bias_tvm = tvm.nd.array(bias, dev)
result = f_run(executable, dev, A_tvm, B_tvm, bias_tvm)
C = A @ B + bias
O = 0.5 * C * (1 + erf(C / np.sqrt(2)))
np.testing.assert_allclose(result.numpy(), O, rtol=5e-2, atol=5e-2)
def constructBatchGEMM_bias2_mul(batch, M, N, K):
with IRBuilder() as ib: # pylint: disable=invalid-name
with I.ir_module() as frame:
with R.function():
R.func_name("main")
A = R.arg(
"A", relax.TensorStructInfo((batch, M, K), A_TYPE)
) # pylint: disable=invalid-name
B = R.arg(
"B", relax.TensorStructInfo((K, N), B_TYPE)
) # pylint: disable=invalid-name
bias = R.arg(
"bias", relax.TensorStructInfo((N,), A_TYPE)
) # pylint: disable=invalid-name
residual = R.arg("residual", relax.TensorStructInfo((batch, M, N), A_TYPE))
with R.dataflow() as df:
C = R.emit(R.matmul(A, B, out_dtype=C_TYPE))
D = R.emit(R.add(C, bias))
E = R.emit(R.multiply(D, residual))
R.output(E)
(E,) = df.output_vars
R.func_ret_value(E)
relax_mod = ib.get()
return relax_mod
@tvm.testing.requires_cutlass
def test_cutlass_batch_dense_bias2_mul():
b, m, n, k = 2, 128, 256, 64
executable = build(constructBatchGEMM_bias2_mul(b, m, n, k))
dev = tvm.cuda()
A = np.random.randn(b, m, k).astype("float16")
B = np.random.randn(k, n).astype("float16")
bias = np.random.randn(n).astype("float16")
residual = np.random.randn(b, m, n).astype("float16")
A_tvm = tvm.nd.array(A, dev)
B_tvm = tvm.nd.array(B, dev)
bias_tvm = tvm.nd.array(bias, dev)
residual_tvm = tvm.nd.array(residual, dev)
result = f_run(executable, dev, A_tvm, B_tvm, bias_tvm, residual_tvm)
np.testing.assert_allclose(result.numpy(), ((A @ B) + bias) * residual, rtol=5e-2, atol=5e-2)
def constructBatchGEMM2_bias(batch, M, N, K):
with IRBuilder() as ib: # pylint: disable=invalid-name
with I.ir_module() as frame:
with R.function():
R.func_name("main")
A = R.arg(
"A", relax.TensorStructInfo((batch, M, K), A_TYPE)
) # pylint: disable=invalid-name
B = R.arg(
"B", relax.TensorStructInfo((batch, K, N), B_TYPE)
) # pylint: disable=invalid-name
bias = R.arg(
"bias", relax.TensorStructInfo((1, N), A_TYPE)
) # pylint: disable=invalid-name
with R.dataflow() as df:
C = R.emit(R.matmul(A, B, out_dtype=C_TYPE))
D = R.emit(R.add(C, bias))
R.output(D)
(D,) = df.output_vars
R.func_ret_value(D)
relax_mod = ib.get()
return relax_mod
@tvm.testing.requires_cutlass
def test_cutlass_batch_dense2_bias():
b, m, n, k = 2, 128, 256, 64
executable = build(constructBatchGEMM2_bias(b, m, n, k))
dev = tvm.cuda()
A = np.random.randn(b, m, k).astype("float16")
B = np.random.randn(b, k, n).astype("float16")
bias = np.random.randn(1, n).astype("float16")
A_tvm = tvm.nd.array(A, dev)
B_tvm = tvm.nd.array(B, dev)
bias_tvm = tvm.nd.array(bias, dev)
result = f_run(executable, dev, A_tvm, B_tvm, bias_tvm)
np.testing.assert_allclose(result.numpy(), A @ B + bias, rtol=5e-2, atol=5e-2)
def constructConv2D(N, C, H, W, KH, KW, O, strides, padding, dilation):
from tvm.script.ir_builder import IRBuilder
from tvm.script.ir_builder import ir as I
from tvm.script.ir_builder import relax as R
from tvm.script.ir_builder import tir as T
with IRBuilder() as ib: # pylint: disable=invalid-name
with I.ir_module() as frame:
with R.function():
R.func_name("main")
x = R.arg(
"x", relax.TensorStructInfo((N, H, W, C), A_TYPE)
) # pylint: disable=invalid-name
w = R.arg(
"w", relax.TensorStructInfo((O, KH, KW, C), B_TYPE)
) # pylint: disable=invalid-name
with R.dataflow() as df:
C = R.emit(
R.nn.conv2d(
x,
w,
strides=strides,
padding=padding,
dilation=dilation,
groups=1,
data_layout="NHWC",
kernel_layout="OHWI",
out_layout="NHWC",
out_dtype=C_TYPE,
)
)
R.output(C)
(C,) = df.output_vars
R.func_ret_value(C)
mod = ib.get()
return mod
@tvm.testing.requires_cutlass
def test_cutlass_conv2d():
n, c, h, w = 1, 3, 224, 224
kh, kw, o = 3, 3, 64
for strides in [(1, 1), (2, 2)]:
for padding in [(0, 0), (3, 3)]:
for dilation in [(1, 1), (4, 4)]:
mod = constructConv2D(n, c, h, w, kh, kw, o, strides, padding, dilation)
executable = build(mod)
dev = tvm.cuda()
np.random.seed(0)
A = np.random.randn(n, h, w, c).astype("float16")
B = np.random.randn(o, kh, kw, c).astype("float16")
A_tvm = tvm.nd.array(A, dev)
B_tvm = tvm.nd.array(B, dev)
result = f_run(executable, dev, A_tvm, B_tvm)
result_ref = build_and_run_reference(mod, [A, B])
np.testing.assert_allclose(
result.numpy(),
result_ref,
rtol=5e-2,
atol=5e-2,
)
def constructConv2D_bias(N, C, H, W, KH, KW, O, strides, padding, dilation):
from tvm.script.ir_builder import IRBuilder
from tvm.script.ir_builder import ir as I
from tvm.script.ir_builder import relax as R
from tvm.script.ir_builder import tir as T
with IRBuilder() as ib: # pylint: disable=invalid-name
with I.ir_module() as frame:
with R.function():
R.func_name("main")
x = R.arg(
"x", relax.TensorStructInfo((N, H, W, C), A_TYPE)
) # pylint: disable=invalid-name
w = R.arg(
"w", relax.TensorStructInfo((O, KH, KW, C), B_TYPE)
) # pylint: disable=invalid-name
bias = R.arg(
"bias", relax.TensorStructInfo((1, 1, 1, O), A_TYPE)
) # pylint: disable=invalid-name
with R.dataflow() as df:
C = R.emit(
R.nn.conv2d(
x,
w,
strides=strides,
padding=padding,
dilation=dilation,
groups=1,
data_layout="NHWC",
kernel_layout="OHWI",
out_layout="NHWC",
out_dtype=C_TYPE,
)
)
D = R.emit(R.add(C, bias))
R.output(D)
(D,) = df.output_vars
R.func_ret_value(D)
mod = ib.get()
return mod
@tvm.testing.requires_cutlass
def test_cutlass_conv2d_bias():
c, h, w = 3, 224, 224
kh, kw, o = 3, 3, 64
for n in [1, 2]:
for strides in [(1, 1), (2, 2)]:
for padding in [(0, 0), (3, 3)]:
for dilation in [(1, 1), (4, 4)]:
mod = constructConv2D_bias(n, c, h, w, kh, kw, o, strides, padding, dilation)
executable = build(mod)
dev = tvm.cuda()
np.random.seed(0)
A = np.random.randn(n, h, w, c).astype("float16")
B = np.random.randn(o, kh, kw, c).astype("float16")
bias = np.random.randn(1, 1, 1, o).astype("float16")
A_tvm = tvm.nd.array(A, dev)
B_tvm = tvm.nd.array(B, dev)
bias_tvm = tvm.nd.array(bias, dev)
result = f_run(executable, dev, A_tvm, B_tvm, bias_tvm)
result_ref = build_and_run_reference(mod, [A, B, bias])
np.testing.assert_allclose(
result.numpy(),
result_ref,
rtol=5e-2,
atol=5e-2,
)
def constructConv2D_bias_add(N, C, H, W, KH, KW, O, OH, OW, strides, padding, dilation):
from tvm.script.ir_builder import IRBuilder
from tvm.script.ir_builder import ir as I
from tvm.script.ir_builder import relax as R
from tvm.script.ir_builder import tir as T
with IRBuilder() as ib: # pylint: disable=invalid-name
with I.ir_module() as frame:
with R.function():
R.func_name("main")
x = R.arg(
"x", relax.TensorStructInfo((N, H, W, C), A_TYPE)
) # pylint: disable=invalid-name
w = R.arg(
"w", relax.TensorStructInfo((O, KH, KW, C), B_TYPE)
) # pylint: disable=invalid-name
bias = R.arg(
"bias", relax.TensorStructInfo((1, 1, 1, O), A_TYPE)
) # pylint: disable=invalid-name
res = R.arg(
"res", relax.TensorStructInfo((N, OH, OW, O), A_TYPE)
) # pylint: disable=invalid-name
with R.dataflow() as df:
C = R.emit(
R.nn.conv2d(
x,
w,
strides=strides,
padding=padding,
dilation=dilation,
groups=1,
data_layout="NHWC",
kernel_layout="OHWI",
out_layout="NHWC",
out_dtype=C_TYPE,
)
)
D = R.emit(R.add(C, bias))
E = R.emit(R.add(D, res))
R.output(E)
(E,) = df.output_vars
R.func_ret_value(E)
mod = ib.get()
return mod
@tvm.testing.requires_cutlass
def test_cutlass_conv2d_bias_add():
n, c, h, w = 2, 3, 224, 224
kh, kw, o = 3, 3, 64
for strides in [(1, 1), (2, 2)]:
for padding in [(0, 0), (3, 3)]:
for dilation in [(1, 1), (4, 4)]:
oh = (h + 2 * padding[0] - dilation[0] * (kh - 1) - 1) // strides[0] + 1
ow = (w + 2 * padding[1] - dilation[1] * (kw - 1) - 1) // strides[1] + 1
mod = constructConv2D_bias_add(
n, c, h, w, kh, kw, o, oh, ow, strides, padding, dilation
)
executable = build(mod)
dev = tvm.cuda()
np.random.seed(0)
A = np.random.randn(n, h, w, c).astype("float16")
B = np.random.randn(o, kh, kw, c).astype("float16")
bias = np.random.randn(1, 1, 1, o).astype("float16")
res = np.random.randn(n, oh, ow, o).astype("float16")
A_tvm = tvm.nd.array(A, dev)
B_tvm = tvm.nd.array(B, dev)
bias_tvm = tvm.nd.array(bias, dev)
res_tvm = tvm.nd.array(res, dev)
result = f_run(executable, dev, A_tvm, B_tvm, bias_tvm, res_tvm)
result_ref = build_and_run_reference(mod, [A, B, bias, res])
np.testing.assert_allclose(
result.numpy(),
result_ref,
rtol=5e-2,
atol=5e-2,
)
if __name__ == "__main__":
tvm.testing.main()