Skip to content
Open
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
3 changes: 3 additions & 0 deletions docs/OperatorKernels.md
Original file line number Diff line number Diff line change
Expand Up @@ -703,6 +703,9 @@ The **OpSet Version** column uses the following notation:
|||14|**T** = tensor(double), tensor(float), tensor(float16)<br/> **U** = tensor(double), tensor(float), tensor(float16)|
|||[9, 13]|**T** = tensor(double), tensor(float), tensor(float16)|
|||[7, 8]|**T** = tensor(double), tensor(float), tensor(float16)|
|BitwiseAnd|*in* A:**T**<br> *in* B:**T**<br> *out* C:**T**|18+|**T** = tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)|
|BitwiseNot|*in* X:**T**<br> *out* Y:**T**|18+|**T** = tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)|
|BitwiseOr|*in* A:**T**<br> *in* B:**T**<br> *out* C:**T**|18+|**T** = tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)|
|Cast|*in* input:**T1**<br> *out* output:**T2**|28+|**T1** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(float4e2m1), tensor(float8e4m3fn), tensor(float8e5m2), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)<br/> **T2** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(float4e2m1), tensor(float8e4m3fn), tensor(float8e5m2), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)|
|||[25, 27]|**T1** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(float4e2m1), tensor(float8e4m3fn), tensor(float8e5m2), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)<br/> **T2** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(float4e2m1), tensor(float8e4m3fn), tensor(float8e5m2), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)|
|||[23, 24]|**T1** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(float4e2m1), tensor(float8e4m3fn), tensor(float8e5m2), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)<br/> **T2** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(float4e2m1), tensor(float8e4m3fn), tensor(float8e5m2), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)|
Expand Down
48 changes: 48 additions & 0 deletions onnxruntime/core/providers/cuda/cuda_execution_provider.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1528,6 +1528,30 @@ class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain,
class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 17, MLFloat16, LayerNormalization);

// Opset 18
class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 18, uint8_t, BitwiseAnd);
class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 18, uint16_t, BitwiseAnd);
class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 18, uint32_t, BitwiseAnd);
class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 18, uint64_t, BitwiseAnd);
class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 18, int8_t, BitwiseAnd);
class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 18, int16_t, BitwiseAnd);
class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 18, int32_t, BitwiseAnd);
class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 18, int64_t, BitwiseAnd);
class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 18, uint8_t, BitwiseOr);
class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 18, uint16_t, BitwiseOr);
class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 18, uint32_t, BitwiseOr);
class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 18, uint64_t, BitwiseOr);
class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 18, int8_t, BitwiseOr);
class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 18, int16_t, BitwiseOr);
class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 18, int32_t, BitwiseOr);
class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 18, int64_t, BitwiseOr);
class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 18, uint8_t, BitwiseNot);
class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 18, uint16_t, BitwiseNot);
class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 18, uint32_t, BitwiseNot);
class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 18, uint64_t, BitwiseNot);
class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 18, int8_t, BitwiseNot);
class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 18, int16_t, BitwiseNot);
class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 18, int32_t, BitwiseNot);
class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 18, int64_t, BitwiseNot);
class ONNX_OPERATOR_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 18, Split);

class ONNX_OPERATOR_VERSIONED_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 18, 19, float, ReduceMax);
Expand Down Expand Up @@ -2853,6 +2877,30 @@ static Status RegisterCudaKernels(KernelRegistry& kernel_registry) {
BuildKernelCreateInfo<ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 17, MLFloat16, LayerNormalization)>,

// Opset 18
BuildKernelCreateInfo<ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 18, uint8_t, BitwiseAnd)>,
BuildKernelCreateInfo<ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 18, uint16_t, BitwiseAnd)>,
BuildKernelCreateInfo<ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 18, uint32_t, BitwiseAnd)>,
BuildKernelCreateInfo<ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 18, uint64_t, BitwiseAnd)>,
BuildKernelCreateInfo<ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 18, int8_t, BitwiseAnd)>,
BuildKernelCreateInfo<ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 18, int16_t, BitwiseAnd)>,
BuildKernelCreateInfo<ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 18, int32_t, BitwiseAnd)>,
BuildKernelCreateInfo<ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 18, int64_t, BitwiseAnd)>,
BuildKernelCreateInfo<ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 18, uint8_t, BitwiseOr)>,
BuildKernelCreateInfo<ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 18, uint16_t, BitwiseOr)>,
BuildKernelCreateInfo<ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 18, uint32_t, BitwiseOr)>,
BuildKernelCreateInfo<ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 18, uint64_t, BitwiseOr)>,
BuildKernelCreateInfo<ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 18, int8_t, BitwiseOr)>,
BuildKernelCreateInfo<ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 18, int16_t, BitwiseOr)>,
BuildKernelCreateInfo<ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 18, int32_t, BitwiseOr)>,
BuildKernelCreateInfo<ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 18, int64_t, BitwiseOr)>,
BuildKernelCreateInfo<ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 18, uint8_t, BitwiseNot)>,
BuildKernelCreateInfo<ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 18, uint16_t, BitwiseNot)>,
BuildKernelCreateInfo<ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 18, uint32_t, BitwiseNot)>,
BuildKernelCreateInfo<ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 18, uint64_t, BitwiseNot)>,
BuildKernelCreateInfo<ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 18, int8_t, BitwiseNot)>,
BuildKernelCreateInfo<ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 18, int16_t, BitwiseNot)>,
BuildKernelCreateInfo<ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 18, int32_t, BitwiseNot)>,
BuildKernelCreateInfo<ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 18, int64_t, BitwiseNot)>,
BuildKernelCreateInfo<ONNX_OPERATOR_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 18, Split)>,
BuildKernelCreateInfo<ONNX_OPERATOR_VERSIONED_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 18, 19, float, ReduceMin)>,
BuildKernelCreateInfo<ONNX_OPERATOR_VERSIONED_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 18, 19, double, ReduceMin)>,
Expand Down
20 changes: 20 additions & 0 deletions onnxruntime/core/providers/cuda/math/binary_elementwise_ops.cc
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,26 @@ BINARY_OP_REGISTER_VERSIONED_CLASS_HFD(Pow, Pow_7, 7, 11)
BINARY_LOGICALOP_TYPED(And, 7, bool)
BINARY_LOGICALOP_TYPED(Or, 7, bool)
BINARY_LOGICALOP_TYPED(Xor, 7, bool)

#define BINARY_BITWISE_OP_TYPED(name, class_name, T) \
BINARY_ELEMENTWISE_REGISTER_KERNEL_TYPED_V(name, class_name, 18, T) \
BINARY_ELEMENTWISE_COMPUTE(class_name, T)

#define BINARY_BITWISE_OP(name, class_name) \
BINARY_BITWISE_OP_TYPED(name, class_name, uint8_t) \
BINARY_BITWISE_OP_TYPED(name, class_name, uint16_t) \
BINARY_BITWISE_OP_TYPED(name, class_name, uint32_t) \
BINARY_BITWISE_OP_TYPED(name, class_name, uint64_t) \
BINARY_BITWISE_OP_TYPED(name, class_name, int8_t) \
BINARY_BITWISE_OP_TYPED(name, class_name, int16_t) \
BINARY_BITWISE_OP_TYPED(name, class_name, int32_t) \
BINARY_BITWISE_OP_TYPED(name, class_name, int64_t)

BINARY_BITWISE_OP(BitwiseAnd, And)
BINARY_BITWISE_OP(BitwiseOr, Or)

#undef BINARY_BITWISE_OP
#undef BINARY_BITWISE_OP_TYPED
BINARY_OP_VERSIONED_HFD(PRelu, 7, 8)
BINARY_OP_VERSIONED_HFD(PRelu, 9, 15)
// Opset-16 adds BFloat16 to allowed types for the PRelu operator
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,18 @@ SPECIALIZED_BINARY_ELEMENTWISE_IMPL_BWUZCSILHFD(Div)
SPECIALIZED_BINARY_ELEMENTWISE_IMPL_HFD(Pow_7)
SPECIALIZED_BINARY_ELEMENTWISE_IMPL(And, bool)
SPECIALIZED_BINARY_ELEMENTWISE_IMPL(Or, bool)
#define SPECIALIZED_BINARY_BITWISE_IMPL(name) \
SPECIALIZED_BINARY_ELEMENTWISE_IMPL(name, uint8_t) \
SPECIALIZED_BINARY_ELEMENTWISE_IMPL(name, uint16_t) \
SPECIALIZED_BINARY_ELEMENTWISE_IMPL_UZIL(name) \
SPECIALIZED_BINARY_ELEMENTWISE_IMPL(name, int8_t) \
SPECIALIZED_BINARY_ELEMENTWISE_IMPL(name, int16_t)

SPECIALIZED_BINARY_BITWISE_IMPL(And)
SPECIALIZED_BINARY_BITWISE_IMPL(Or)

#undef SPECIALIZED_BINARY_BITWISE_IMPL

SPECIALIZED_BINARY_ELEMENTWISE_IMPL(Xor, bool)
SPECIALIZED_BINARY_ELEMENTWISE_IMPL_HFD(PRelu)
SPECIALIZED_BINARY_ELEMENTWISE_IMPL_UZILHFD(Max)
Expand Down
8 changes: 8 additions & 0 deletions onnxruntime/core/providers/cuda/math/unary_elementwise_ops.cc
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,14 @@ UNARY_OP_HFDX(Erf, 13)
UNARY_OP_BWUZCSILHFDX(Sign, 13)

UNARY_LOGICALOP_NOT_TYPED(1, bool)
UNARY_OP_TYPED(BitwiseNot, 18, uint8_t)
UNARY_OP_TYPED(BitwiseNot, 18, uint16_t)
UNARY_OP_TYPED(BitwiseNot, 18, uint32_t)
UNARY_OP_TYPED(BitwiseNot, 18, uint64_t)
UNARY_OP_TYPED(BitwiseNot, 18, int8_t)
UNARY_OP_TYPED(BitwiseNot, 18, int16_t)
UNARY_OP_TYPED(BitwiseNot, 18, int32_t)
UNARY_OP_TYPED(BitwiseNot, 18, int64_t)
UNARY_OP_VERSIONED_HFD(Round, 11, 21)
UNARY_OP_HFD(Round, 22)
UNARY_OP_VERSIONED_HFD(Cos, 7, 21)
Expand Down
7 changes: 7 additions & 0 deletions onnxruntime/core/providers/cuda/math/unary_elementwise_ops.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,13 @@ class Not final : public UnaryElementwise {
Status ComputeInternal(OpKernelContext* context) const override;
};

template <typename T>
class BitwiseNot final : public UnaryElementwise {
public:
BitwiseNot(const OpKernelInfo& info) : UnaryElementwise(info) {}
Status ComputeInternal(OpKernelContext* context) const override;
};

template <typename T>
class Round final : public UnaryElementwise {
public:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,14 @@ SPECIALIZED_UNARY_ELEMENTWISE_IMPL_HFD(Round)
SPECIALIZED_UNARY_ELEMENTWISE_IMPL_HFDX(Sin)
SPECIALIZED_UNARY_ELEMENTWISE_IMPL_HFDX(Cos)
SPECIALIZED_UNARY_ELEMENTWISE_IMPL(Not, bool)
SPECIALIZED_UNARY_ELEMENTWISE_IMPL(BitwiseNot, uint8_t)
SPECIALIZED_UNARY_ELEMENTWISE_IMPL(BitwiseNot, uint16_t)
SPECIALIZED_UNARY_ELEMENTWISE_IMPL(BitwiseNot, uint32_t)
SPECIALIZED_UNARY_ELEMENTWISE_IMPL(BitwiseNot, uint64_t)
SPECIALIZED_UNARY_ELEMENTWISE_IMPL(BitwiseNot, int8_t)
SPECIALIZED_UNARY_ELEMENTWISE_IMPL(BitwiseNot, int16_t)
SPECIALIZED_UNARY_ELEMENTWISE_IMPL(BitwiseNot, int32_t)
SPECIALIZED_UNARY_ELEMENTWISE_IMPL(BitwiseNot, int64_t)
SPECIALIZED_UNARY_ELEMENTWISE_IMPL_BWUZCSILHFD(Sign)

// When casting, half needs to be converted via float type from most other types
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ namespace cuda {
UNARY_OP_NAME_EXPR(Log, _Log(a)) \
UNARY_OP_NAME_EXPR(Erf, _Erf(a)) \
UNARY_OP_NAME_EXPR(Not, !a) \
UNARY_OP_NAME_EXPR(BitwiseNot, ~a) \
UNARY_OP_NAME_EXPR(Round, _Round(a)) \
UNARY_OP_NAME_EXPR(Sin, _Sin(a)) \
UNARY_OP_NAME_EXPR(Cos, _Cos(a)) \
Expand Down
136 changes: 136 additions & 0 deletions onnxruntime/test/providers/cuda/bitwise_ops_test.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

#include <cstdint>
#include <initializer_list>
#include <limits>
#include <string>
#include <vector>

#include "gtest/gtest.h"
#include "core/session/onnxruntime_session_options_config_keys.h"
#include "test/providers/provider_test_utils.h"
#include "test/util/include/default_providers.h"

namespace onnxruntime {
namespace test {
namespace {

template <typename T>
void RunCudaBitwise(const char* op, int opset,
const std::vector<int64_t>& lhs_shape, const std::vector<T>& lhs,
const std::vector<int64_t>& rhs_shape, const std::vector<T>& rhs,
const std::vector<int64_t>& output_shape, const std::vector<T>& expected) {
SCOPED_TRACE(std::string(op) + " opset=" + std::to_string(opset));
OpTester test(op, opset);
const bool unary = std::string(op) == "BitwiseNot";
test.AddInput<T>(unary ? "X" : "A", lhs_shape, lhs);
if (!unary) {
test.AddInput<T>("B", rhs_shape, rhs);
}
test.AddOutput<T>(unary ? "Y" : "C", output_shape, expected);
SessionOptions options;
ASSERT_STATUS_OK(options.config_options.AddConfigEntry(kOrtSessionOptionsDisableCPUEPFallback, "1"));
test.Config(options).ConfigEp(DefaultCudaExecutionProvider()).RunWithConfig();
}

template <typename T>
class CudaBitwiseOpTest : public ::testing::Test {
protected:
void SetUp() override {
if (!DefaultCudaExecutionProvider()) {
GTEST_SKIP() << "CUDA execution provider is unavailable";
}
}
};

using IntegerTypes = ::testing::Types<int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t, int64_t, uint64_t>;
TYPED_TEST_SUITE(CudaBitwiseOpTest, IntegerTypes);

TYPED_TEST(CudaBitwiseOpTest, IntegerExtremaBroadcastAndTails) {
using T = TypeParam;
const std::vector<T> values{
T{0}, T{1}, std::numeric_limits<T>::max(), std::numeric_limits<T>::lowest(),
static_cast<T>(-1), static_cast<T>(UINT64_C(0x5555555555555555) & std::numeric_limits<T>::max()),
static_cast<T>(UINT64_C(0x2aaaaaaaaaaaaaaa) & std::numeric_limits<T>::max())};

for (int opset : {18, 24}) {
for (const char* op : {"BitwiseAnd", "BitwiseOr", "BitwiseNot"}) {
const auto apply = [op](T a, T b) -> T {
if (std::string(op) == "BitwiseAnd") {
return static_cast<T>(a & b);
}
if (std::string(op) == "BitwiseOr") {
return static_cast<T>(a | b);
}
return static_cast<T>(~a);
};

for (int64_t size : {0, 1, 7, 255, 256, 257, 1025}) {
SCOPED_TRACE("size=" + std::to_string(size));
std::vector<T> lhs, rhs, expected;
lhs.reserve(static_cast<size_t>(size));
rhs.reserve(static_cast<size_t>(size));
expected.reserve(static_cast<size_t>(size));
for (int64_t i = 0; i < size; ++i) {
lhs.push_back(values[static_cast<size_t>(i) % values.size()]);
rhs.push_back(values[(static_cast<size_t>(i) / values.size() + 2) % values.size()]);
expected.push_back(apply(lhs.back(), rhs.back()));
}
RunCudaBitwise(op, opset, {size}, lhs, {size}, rhs, {size}, expected);
}

const T scalar = std::numeric_limits<T>::max();
std::vector<T> expected;
expected.reserve(values.size());
for (T value : values) {
expected.push_back(apply(value, scalar));
}
RunCudaBitwise(op, opset, {7}, values, {}, {scalar}, {7}, expected);
RunCudaBitwise<T>(op, opset, {}, {scalar}, {}, {scalar}, {}, {apply(scalar, scalar)});

if (std::string(op) != "BitwiseNot") {
RunCudaBitwise(op, opset, {}, {scalar}, {7}, values, {7}, expected);
RunCudaBitwise<T>(op, opset, {2, 0, 3}, {}, {1, 3}, {T{0}, T{1}, scalar}, {2, 0, 3}, {});
const std::vector<T> lhs(values.begin(), values.begin() + 6);
const std::vector<T> rhs{values[2], values[3], values[4], values[5]};
expected.clear();
for (size_t batch = 0; batch < 2; ++batch) {
for (T b : rhs) {
for (size_t col = 0; col < 3; ++col) {
expected.push_back(apply(lhs[batch * 3 + col], b));
}
}
}
RunCudaBitwise(op, opset, {2, 1, 3}, lhs, {1, 4, 1}, rhs, {2, 4, 3}, expected);
RunCudaBitwise(op, opset, {1, 4, 1}, rhs, {2, 1, 3}, lhs, {2, 4, 3}, expected);
}
}
}
}

TEST(CudaBitwiseLogicalTest, BooleanOpsUnchanged) {
if (!DefaultCudaExecutionProvider()) {
GTEST_SKIP() << "CUDA execution provider is unavailable";
}
const auto run = [](const char* op, int opset, std::initializer_list<bool> expected) {
SCOPED_TRACE(op);
const bool unary = std::string(op) == "Not";
OpTester test(op, opset);
test.AddInput<bool>(unary ? "X" : "A", {4}, {false, false, true, true});
if (!unary) {
test.AddInput<bool>("B", {4}, {false, true, false, true});
}
test.AddOutput<bool>(unary ? "Y" : "C", {4}, expected);
SessionOptions options;
ASSERT_STATUS_OK(options.config_options.AddConfigEntry(kOrtSessionOptionsDisableCPUEPFallback, "1"));
test.Config(options).ConfigEp(DefaultCudaExecutionProvider()).RunWithConfig();
};
run("And", 7, {false, false, false, true});
run("Or", 7, {false, true, true, true});
run("Not", 1, {true, true, false, false});
}

} // namespace
} // namespace test
} // namespace onnxruntime
Loading