From 24952fa871cacb332a7b555d22966fcc42044a89 Mon Sep 17 00:00:00 2001 From: Yohann Dudouit Date: Mon, 2 Mar 2026 14:48:20 -0800 Subject: [PATCH 01/11] Add support for int32_t and int64_t. --- src/AMSlib/AMSTensor.cpp | 113 ++++++++++++++++++++----------- src/AMSlib/include/AMSTensor.hpp | 16 +++-- src/AMSlib/include/AMSTypes.hpp | 8 ++- src/AMSlib/wf/interface.cpp | 16 ++++- src/AMSlib/wf/utils.hpp | 4 ++ 5 files changed, 108 insertions(+), 49 deletions(-) diff --git a/src/AMSlib/AMSTensor.cpp b/src/AMSlib/AMSTensor.cpp index 83566dbd..8362f414 100644 --- a/src/AMSlib/AMSTensor.cpp +++ b/src/AMSlib/AMSTensor.cpp @@ -33,6 +33,25 @@ bool AMSTensor::isContiguous(AMSTensor::IntDimType expected_stride) const return true; } +namespace { +template +constexpr AMSDType scalar_to_ams_dtype() +{ + using U = std::remove_cv_t; + if constexpr (std::is_same_v) { + return AMS_SINGLE; + } else if constexpr (std::is_same_v) { + return AMS_DOUBLE; + } else if constexpr (std::is_same_v) { + return AMS_INT32; + } else if constexpr (std::is_same_v) { + return AMS_INT64; + } else { + static_assert(!sizeof(T), "Unsupported AMS scalar type"); + } +} +} + AMSTensor::AMSTensor(uint8_t* data, ams::ArrayRef shapes, ams::ArrayRef strides, @@ -54,60 +73,36 @@ AMSTensor::AMSTensor(uint8_t* data, } } -template +template AMSTensor AMSTensor::create(ams::ArrayRef shapes, ams::ArrayRef strides, AMSResourceType location) { auto numElements = computeNumElements(shapes); auto& rm = ams::ResourceManager::getInstance(); - if constexpr ((std::is_same_v) || - (std::is_same_v)) { - float* _data = rm.allocate(numElements, location, sizeof(float)); - return AMSTensor(reinterpret_cast(_data), - shapes, - strides, - AMS_SINGLE, - location); - } else if constexpr ((std::is_same_v) || - (std::is_same_v)) { - double* _data = rm.allocate(numElements, location, sizeof(double)); - return AMSTensor(reinterpret_cast(_data), - shapes, - strides, - AMS_DOUBLE, - location); - } else { - // This should never happen due to the type restriction - static_assert(std::is_same_v || - std::is_same_v, - "AMSTensor only supports float or double tensor creation"); - } + using U = std::remove_cv_t; + U* data = rm.allocate(numElements, location, sizeof(U)); + return AMSTensor(reinterpret_cast(data), + shapes, + strides, + scalar_to_ams_dtype(), + location); } -template -AMSTensor AMSTensor::view(FPType* data, +template +AMSTensor AMSTensor::view(ScalarType* data, ams::ArrayRef shapes, ams::ArrayRef strides, AMSResourceType location) { - if constexpr ((std::is_same_v) || - (std::is_same_v)) { - return AMSTensor( - (uint8_t*)data, shapes, strides, AMS_SINGLE, location, true); - } else if constexpr ((std::is_same_v) || - (std::is_same_v)) { - return AMSTensor( - (uint8_t*)data, shapes, strides, AMS_DOUBLE, location, true); - } else { - static_assert(std::is_same_v || - std::is_same_v || - std::is_same_v || - std::is_same_v, - "AMSTensor only supports float or double tensor view"); - } - throw std::runtime_error("Should never get here\n"); + using U = std::remove_cv_t; + return AMSTensor(reinterpret_cast(const_cast(data)), + shapes, + strides, + scalar_to_ams_dtype(), + location, + true); } AMSTensor AMSTensor::view(AMSTensor& tensor) @@ -122,6 +117,16 @@ AMSTensor AMSTensor::view(AMSTensor& tensor) tensor._shape, tensor._strides, tensor._location); + else if (tensor._dType == AMS_INT32) + return AMSTensor::view((int32_t*)tensor._data, + tensor._shape, + tensor._strides, + tensor._location); + else if (tensor._dType == AMS_INT64) + return AMSTensor::view((int64_t*)tensor._data, + tensor._shape, + tensor._strides, + tensor._location); throw std::runtime_error( "Creating view through copying constructor has incorrect dtype"); } @@ -193,6 +198,10 @@ AMSTensor AMSTensor::transpose(AMSTensor::IntDimType axis1, return view((double*)_data, newShape, newStrides, _location); else if (dType() == AMSDType::AMS_SINGLE) return view((float*)_data, newShape, newStrides, _location); + else if (dType() == AMSDType::AMS_INT32) + return view((int32_t*)_data, newShape, newStrides, _location); + else if (dType() == AMSDType::AMS_INT64) + return view((int64_t*)_data, newShape, newStrides, _location); // NOTE: Use defensive programming here and just crash. We can fix a better interface later // for error handling. throw std::runtime_error("Unknow data type in transpose\n"); @@ -204,6 +213,12 @@ template AMSTensor AMSTensor::create(ams::ArrayRef, template AMSTensor AMSTensor::create(ams::ArrayRef, ams::ArrayRef, AMSResourceType); +template AMSTensor AMSTensor::create(ams::ArrayRef, + ams::ArrayRef, + AMSResourceType); +template AMSTensor AMSTensor::create(ams::ArrayRef, + ams::ArrayRef, + AMSResourceType); template AMSTensor AMSTensor::view(float*, ams::ArrayRef, @@ -213,6 +228,14 @@ template AMSTensor AMSTensor::view(double*, ams::ArrayRef, ams::ArrayRef, AMSResourceType); +template AMSTensor AMSTensor::view(int32_t*, + ams::ArrayRef, + ams::ArrayRef, + AMSResourceType); +template AMSTensor AMSTensor::view(int64_t*, + ams::ArrayRef, + ams::ArrayRef, + AMSResourceType); template AMSTensor AMSTensor::view(const float*, ams::ArrayRef, @@ -222,3 +245,11 @@ template AMSTensor AMSTensor::view(const double*, ams::ArrayRef, ams::ArrayRef, AMSResourceType); +template AMSTensor AMSTensor::view(const int32_t*, + ams::ArrayRef, + ams::ArrayRef, + AMSResourceType); +template AMSTensor AMSTensor::view(const int64_t*, + ams::ArrayRef, + ams::ArrayRef, + AMSResourceType); diff --git a/src/AMSlib/include/AMSTensor.hpp b/src/AMSlib/include/AMSTensor.hpp index 53483838..a8c483f7 100644 --- a/src/AMSlib/include/AMSTensor.hpp +++ b/src/AMSlib/include/AMSTensor.hpp @@ -66,8 +66,7 @@ class AMSTensor * @param[in] location The memory location (e.g., CPU, GPU). * @return A new AMSTensor with allocated memory. */ - template ::value>> + template static AMSTensor create(ams::ArrayRef shapes, ams::ArrayRef strides, AMSResourceType location); @@ -81,9 +80,8 @@ class AMSTensor * @param[in] location The memory location (e.g., CPU, GPU). * @return A new AMSTensor that acts as a view of the existing data. */ - template ::value>> - static AMSTensor view(FPType* data, + template + static AMSTensor view(ScalarType* data, ams::ArrayRef shapes, ams::ArrayRef strides, AMSResourceType location); @@ -150,4 +148,12 @@ extern template AMSTensor AMSTensor::create( ams::ArrayRef shapes, ams::ArrayRef strides, AMSResourceType location); +extern template AMSTensor AMSTensor::create( + ams::ArrayRef shapes, + ams::ArrayRef strides, + AMSResourceType location); +extern template AMSTensor AMSTensor::create( + ams::ArrayRef shapes, + ams::ArrayRef strides, + AMSResourceType location); } // namespace ams diff --git a/src/AMSlib/include/AMSTypes.hpp b/src/AMSlib/include/AMSTypes.hpp index 19e13904..de9f5249 100644 --- a/src/AMSlib/include/AMSTypes.hpp +++ b/src/AMSlib/include/AMSTypes.hpp @@ -2,7 +2,13 @@ namespace ams { -typedef enum { AMS_SINGLE = 0, AMS_DOUBLE, AMS_UNKNOWN_TYPE } AMSDType; +typedef enum { + AMS_SINGLE = 0, + AMS_DOUBLE, + AMS_INT32, + AMS_INT64, + AMS_UNKNOWN_TYPE +} AMSDType; typedef enum { AMS_UNKNOWN = -1, diff --git a/src/AMSlib/wf/interface.cpp b/src/AMSlib/wf/interface.cpp index 8fbda4ac..b413f26c 100644 --- a/src/AMSlib/wf/interface.cpp +++ b/src/AMSlib/wf/interface.cpp @@ -33,8 +33,8 @@ static AMSDType torchDTypeToAMSType(torch::Dtype dtype) {torch::kFloat, AMSDType::AMS_SINGLE}, // Alias for float32 {torch::kFloat64, AMSDType::AMS_DOUBLE}, {torch::kDouble, AMSDType::AMS_DOUBLE}, // Alias for float64 - {torch::kInt32, AMSDType::AMS_UNKNOWN_TYPE}, - {torch::kInt64, AMSDType::AMS_UNKNOWN_TYPE}, + {torch::kInt32, AMSDType::AMS_INT32}, + {torch::kInt64, AMSDType::AMS_INT64}, {torch::kBool, AMSDType::AMS_UNKNOWN_TYPE}, {torch::kUInt8, AMSDType::AMS_UNKNOWN_TYPE}, {torch::kInt8, AMSDType::AMS_UNKNOWN_TYPE}, @@ -66,6 +66,10 @@ static c10::ScalarType amsToTorchDType(const ams::AMSDType dType) return torch::kFloat32; else if (dType == ams::AMSDType::AMS_DOUBLE) return torch::kFloat64; + else if (dType == ams::AMSDType::AMS_INT32) + return torch::kInt32; + else if (dType == ams::AMSDType::AMS_INT64) + return torch::kInt64; throw std::runtime_error("Unknown ams data type"); return torch::kHalf; @@ -91,6 +95,14 @@ static ams::SmallVector torchToAMSTensors( } else if (dType == AMSDType::AMS_DOUBLE) { ams_tensors.push_back( AMSTensor::view(tensor.data_ptr(), shapes, strides, rType)); + } else if (dType == AMSDType::AMS_INT32) { + ams_tensors.push_back( + AMSTensor::view(tensor.data_ptr(), shapes, strides, rType)); + } else if (dType == AMSDType::AMS_INT64) { + ams_tensors.push_back( + AMSTensor::view(tensor.data_ptr(), shapes, strides, rType)); + } else { + throw std::runtime_error("torchToAMSTensors: unsupported tensor scalar type"); } } return ams_tensors; diff --git a/src/AMSlib/wf/utils.hpp b/src/AMSlib/wf/utils.hpp index 9d056a59..59cc352a 100644 --- a/src/AMSlib/wf/utils.hpp +++ b/src/AMSlib/wf/utils.hpp @@ -67,6 +67,10 @@ static inline size_t dtype_to_size(ams::AMSDType dType) return sizeof(double); case ams::AMSDType::AMS_SINGLE: return sizeof(float); + case ams::AMSDType::AMS_INT64: + return sizeof(int64_t); + case ams::AMSDType::AMS_INT32: + return sizeof(int32_t); default: throw std::runtime_error("Requesting the size of unknown object"); } From 806d2c8ad5296b865ed960337ba675c87adf0c27 Mon Sep 17 00:00:00 2001 From: Yohann Dudouit Date: Mon, 2 Mar 2026 14:49:14 -0800 Subject: [PATCH 02/11] Fix typo/bug in AMSEOS. --- examples/ideal_gas/app/eos_ams.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/ideal_gas/app/eos_ams.cpp b/examples/ideal_gas/app/eos_ams.cpp index 16efce3a..6857e725 100644 --- a/examples/ideal_gas/app/eos_ams.cpp +++ b/examples/ideal_gas/app/eos_ams.cpp @@ -45,7 +45,7 @@ void AMSEOS::Eval(const int length, inputs.push_back( std::move(AMSTensor::view(density, {length, 1}, {1, 1}, res_))); inputs.push_back( - std::move(AMSTensor::view(density, {length, 1}, {1, 1}, res_))); + std::move(AMSTensor::view(energy, {length, 1}, {1, 1}, res_))); SmallVector inout; SmallVector outputs; From fbe9fa14bd74c05bc64f592e1af0813ea9c2d36d Mon Sep 17 00:00:00 2001 From: Yohann Date: Mon, 9 Mar 2026 14:26:28 -0700 Subject: [PATCH 03/11] Apply suggestions from code review Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- src/AMSlib/AMSTensor.cpp | 5 +++-- src/AMSlib/wf/interface.cpp | 3 ++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/AMSlib/AMSTensor.cpp b/src/AMSlib/AMSTensor.cpp index 8362f414..45a41e28 100644 --- a/src/AMSlib/AMSTensor.cpp +++ b/src/AMSlib/AMSTensor.cpp @@ -33,7 +33,8 @@ bool AMSTensor::isContiguous(AMSTensor::IntDimType expected_stride) const return true; } -namespace { +namespace +{ template constexpr AMSDType scalar_to_ams_dtype() { @@ -50,7 +51,7 @@ constexpr AMSDType scalar_to_ams_dtype() static_assert(!sizeof(T), "Unsupported AMS scalar type"); } } -} +} // namespace AMSTensor::AMSTensor(uint8_t* data, ams::ArrayRef shapes, diff --git a/src/AMSlib/wf/interface.cpp b/src/AMSlib/wf/interface.cpp index b413f26c..07a6611c 100644 --- a/src/AMSlib/wf/interface.cpp +++ b/src/AMSlib/wf/interface.cpp @@ -102,7 +102,8 @@ static ams::SmallVector torchToAMSTensors( ams_tensors.push_back( AMSTensor::view(tensor.data_ptr(), shapes, strides, rType)); } else { - throw std::runtime_error("torchToAMSTensors: unsupported tensor scalar type"); + throw std::runtime_error( + "torchToAMSTensors: unsupported tensor scalar type"); } } return ams_tensors; From 4341d7aed4f8afd62cf2930aca719d7227767ab8 Mon Sep 17 00:00:00 2001 From: Loic Pottier Date: Fri, 3 Apr 2026 12:52:24 -0700 Subject: [PATCH 04/11] Trigger Build Signed-off-by: Loic Pottier From 8f3fb62db6aaafe9816b1657fb39e1716ee24dd4 Mon Sep 17 00:00:00 2001 From: Loic Pottier Date: Wed, 8 Apr 2026 15:03:05 -0700 Subject: [PATCH 05/11] Deactivating Dane tests Signed-off-by: Loic Pottier --- .gitlab/subscribed-pipelines.yml | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/.gitlab/subscribed-pipelines.yml b/.gitlab/subscribed-pipelines.yml index 569048d1..6a1728a3 100644 --- a/.gitlab/subscribed-pipelines.yml +++ b/.gitlab/subscribed-pipelines.yml @@ -30,19 +30,19 @@ ### # Dane -dane-up-check: - variables: - CI_MACHINE: "dane" - extends: [.machine-check] +# dane-up-check: +# variables: +# CI_MACHINE: "dane" +# extends: [.machine-check] -dane-build-and-test: - variables: - CI_MACHINE: "dane" - JOB_CMD: - value: "scripts/gitlab/ci-build-test.sh" - expand: false - needs: [dane-up-check] - extends: [.build-and-test] +# dane-build-and-test: +# variables: +# CI_MACHINE: "dane" +# JOB_CMD: +# value: "scripts/gitlab/ci-build-test.sh" +# expand: false +# needs: [dane-up-check] +# extends: [.build-and-test] # TIOGA tioga-up-check: From 02abe7a49bcde0bb67eca301b44d857bf81fcde1 Mon Sep 17 00:00:00 2001 From: Yohann Dudouit Date: Thu, 9 Apr 2026 11:37:09 -0700 Subject: [PATCH 06/11] Add unit tests for int support. --- tests/AMSlib/ams_interface/CMakeLists.txt | 3 + tests/AMSlib/ams_interface/int_interface.cpp | 325 ++++++++++++++ tests/AMSlib/wf/CMakeLists.txt | 3 + tests/AMSlib/wf/int_tensors.cpp | 418 +++++++++++++++++++ 4 files changed, 749 insertions(+) create mode 100644 tests/AMSlib/ams_interface/int_interface.cpp create mode 100644 tests/AMSlib/wf/int_tensors.cpp diff --git a/tests/AMSlib/ams_interface/CMakeLists.txt b/tests/AMSlib/ams_interface/CMakeLists.txt index 9250e421..139ca630 100644 --- a/tests/AMSlib/ams_interface/CMakeLists.txt +++ b/tests/AMSlib/ams_interface/CMakeLists.txt @@ -24,3 +24,6 @@ endfunction() BUILD_UNIT_TEST(ams_explicit_end_to_end ams_ete.cpp) ADD_AMS_UNIT_TEST(AMS_EXPLICIT ams_explicit_end_to_end) +BUILD_UNIT_TEST(int_interface int_interface.cpp) +ADD_AMS_UNIT_TEST(AMS_INT_SUPPORT int_interface) + diff --git a/tests/AMSlib/ams_interface/int_interface.cpp b/tests/AMSlib/ams_interface/int_interface.cpp new file mode 100644 index 00000000..b139f671 --- /dev/null +++ b/tests/AMSlib/ams_interface/int_interface.cpp @@ -0,0 +1,325 @@ +/* + * Copyright 2021-2023 Lawrence Livermore National Security, LLC and other + * AMSLib Project Developers + * + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include +#include +#include +#include + +#include "AMS.h" +#include "AMSTensor.hpp" + +using namespace ams; + +// Global test fixture to initialize AMS once for all tests +struct AMSGlobalFixture { + AMSGlobalFixture() { + AMSInit(); + } +}; + +// This creates a single global instance that will initialize AMS before any tests run +static AMSGlobalFixture amsGlobalFixture; + +// Simple computation function for int32_t +void compute_int32(int32_t* input, int32_t* output, int num_elements) +{ + for (int i = 0; i < num_elements; ++i) { + // Simple computation: output = input * 2 + 1 + output[i] = input[i] * 2 + 1; + } +} + +// Simple computation function for int64_t +void compute_int64(int64_t* input, int64_t* output, int num_elements) +{ + for (int i = 0; i < num_elements; ++i) { + // Simple computation: output = input * 3 + 10 + output[i] = input[i] * 3 + 10; + } +} + +CATCH_TEST_CASE("AMS API: int32_t tensor execution without model", + "[ams][api][int32]") +{ + const auto resource = GENERATE(AMSResourceType::AMS_HOST); + constexpr int num_elements = 100; + + CATCH_SECTION("Execute with int32_t inputs and outputs") + { + // Allocate and initialize input data + std::vector input_data(num_elements); + for (int i = 0; i < num_elements; ++i) { + input_data[i] = i; + } + + // Allocate output data + std::vector output_data(num_elements, 0); + + // Create AMS tensors + SmallVector inputs; + SmallVector inouts; + SmallVector outputs; + + SmallVector shape_1d{num_elements}; + SmallVector strides_1d{1}; + + inputs.push_back(AMSTensor::view( + input_data.data(), shape_1d, strides_1d, resource)); + + outputs.push_back(AMSTensor::view( + output_data.data(), shape_1d, strides_1d, resource)); + + // Define computation lambda + DomainLambda computation = [&](const SmallVector& ins, + SmallVector& io, + SmallVector& outs) { + CATCH_REQUIRE(ins.size() == 1); + CATCH_REQUIRE(outs.size() == 1); + CATCH_REQUIRE(ins[0].dType() == AMSDType::AMS_INT32); + CATCH_REQUIRE(outs[0].dType() == AMSDType::AMS_INT32); + + int32_t* in_ptr = ins[0].data(); + int32_t* out_ptr = outs[0].data(); + int count = ins[0].elements(); + + compute_int32(in_ptr, out_ptr, count); + }; + + // Create model and executor (with threshold = 1.0, always use physics) + AMSCAbstrModel model = AMSRegisterAbstractModel( + "int32_test", 1.0, "", false); // No model path, no storage + CATCH_REQUIRE(model >= 0); + + AMSExecutor executor = AMSCreateExecutor(model, 0, 1); + CATCH_REQUIRE(executor >= 0); + + // Execute + AMSExecute(executor, computation, inputs, inouts, outputs); + + // Verify results + for (int i = 0; i < num_elements; ++i) { + int32_t expected = i * 2 + 1; + CATCH_REQUIRE(output_data[i] == expected); + } + + // Note: Not destroying executor to avoid triggering AMSFinalize between tests + // The executor will be cleaned up at program exit + } +} + +CATCH_TEST_CASE("AMS API: int64_t tensor execution without model", + "[ams][api][int64]") +{ + const auto resource = GENERATE(AMSResourceType::AMS_HOST); + constexpr int num_elements = 150; + + CATCH_SECTION("Execute with int64_t inputs and outputs") + { + // Allocate and initialize input data with large values + std::vector input_data(num_elements); + for (int i = 0; i < num_elements; ++i) { + input_data[i] = static_cast(i) * 1000000; + } + + // Allocate output data + std::vector output_data(num_elements, 0); + + // Create AMS tensors + SmallVector inputs; + SmallVector inouts; + SmallVector outputs; + + SmallVector shape_1d{num_elements}; + SmallVector strides_1d{1}; + + inputs.push_back(AMSTensor::view( + input_data.data(), shape_1d, strides_1d, resource)); + + outputs.push_back(AMSTensor::view( + output_data.data(), shape_1d, strides_1d, resource)); + + // Define computation lambda + DomainLambda computation = [&](const SmallVector& ins, + SmallVector& io, + SmallVector& outs) { + CATCH_REQUIRE(ins.size() == 1); + CATCH_REQUIRE(outs.size() == 1); + CATCH_REQUIRE(ins[0].dType() == AMSDType::AMS_INT64); + CATCH_REQUIRE(outs[0].dType() == AMSDType::AMS_INT64); + + int64_t* in_ptr = ins[0].data(); + int64_t* out_ptr = outs[0].data(); + int count = ins[0].elements(); + + compute_int64(in_ptr, out_ptr, count); + }; + + // Create model and executor (with threshold = 1.0, always use physics) + AMSCAbstrModel model = AMSRegisterAbstractModel( + "int64_test", 1.0, "", false); // No model path, no storage + CATCH_REQUIRE(model >= 0); + + AMSExecutor executor = AMSCreateExecutor(model, 0, 1); + CATCH_REQUIRE(executor >= 0); + + // Execute + AMSExecute(executor, computation, inputs, inouts, outputs); + + // Verify results + for (int i = 0; i < num_elements; ++i) { + int64_t expected = static_cast(i) * 1000000 * 3 + 10; + CATCH_REQUIRE(output_data[i] == expected); + } + + // Note: Not destroying executor to avoid triggering AMSFinalize between tests + // The executor will be cleaned up at program exit + } +} + +CATCH_TEST_CASE("AMS API: 2D int32_t tensor execution", "[ams][api][int32][2d]") +{ + const auto resource = GENERATE(AMSResourceType::AMS_HOST); + constexpr int rows = 10; + constexpr int cols = 8; + constexpr int num_elements = rows * cols; + + CATCH_SECTION("Execute with 2D int32_t tensors") + { + // Allocate 2D input data + std::vector input_data(num_elements); + for (int i = 0; i < rows; ++i) { + for (int j = 0; j < cols; ++j) { + input_data[i * cols + j] = i * 10 + j; + } + } + + std::vector output_data(num_elements, 0); + + // Create 2D tensors + SmallVector inputs; + SmallVector inouts; + SmallVector outputs; + + SmallVector shape_2d{rows, cols}; + SmallVector strides_2d{cols, 1}; + + inputs.push_back(AMSTensor::view( + input_data.data(), shape_2d, strides_2d, resource)); + + outputs.push_back(AMSTensor::view( + output_data.data(), shape_2d, strides_2d, resource)); + + // Computation: element-wise doubling + DomainLambda computation = [&](const SmallVector& ins, + SmallVector& io, + SmallVector& outs) { + CATCH_REQUIRE(ins[0].shape().size() == 2); + CATCH_REQUIRE(ins[0].shape()[0] == rows); + CATCH_REQUIRE(ins[0].shape()[1] == cols); + + int32_t* in_ptr = ins[0].data(); + int32_t* out_ptr = outs[0].data(); + + for (int i = 0; i < num_elements; ++i) { + out_ptr[i] = in_ptr[i] * 2; + } + }; + + AMSCAbstrModel model = AMSRegisterAbstractModel( + "int32_2d_test", 1.0, "", false); + AMSExecutor executor = AMSCreateExecutor(model, 0, 1); + + AMSExecute(executor, computation, inputs, inouts, outputs); + + // Verify + for (int i = 0; i < rows; ++i) { + for (int j = 0; j < cols; ++j) { + int idx = i * cols + j; + int32_t expected = (i * 10 + j) * 2; + CATCH_REQUIRE(output_data[idx] == expected); + } + } + + // Note: Not destroying executor to avoid triggering AMSFinalize between tests + // The executor will be cleaned up at program exit + } +} + +CATCH_TEST_CASE("AMS API: Mixed type tensors", "[ams][api][mixed]") +{ + const auto resource = GENERATE(AMSResourceType::AMS_HOST); + constexpr int num_elements = 50; + + CATCH_SECTION("Execute with mixed float and int32_t tensors") + { + // Float input + std::vector float_input(num_elements); + for (int i = 0; i < num_elements; ++i) { + float_input[i] = static_cast(i) * 1.5f; + } + + // Int32 input + std::vector int_input(num_elements); + for (int i = 0; i < num_elements; ++i) { + int_input[i] = i * 2; + } + + // Int32 output + std::vector output_data(num_elements, 0); + + SmallVector inputs; + SmallVector inouts; + SmallVector outputs; + + SmallVector shape_1d{num_elements}; + SmallVector strides_1d{1}; + + inputs.push_back(AMSTensor::view( + float_input.data(), shape_1d, strides_1d, resource)); + + inputs.push_back(AMSTensor::view( + int_input.data(), shape_1d, strides_1d, resource)); + + outputs.push_back(AMSTensor::view( + output_data.data(), shape_1d, strides_1d, resource)); + + DomainLambda computation = [&](const SmallVector& ins, + SmallVector& io, + SmallVector& outs) { + CATCH_REQUIRE(ins.size() == 2); + CATCH_REQUIRE(ins[0].dType() == AMSDType::AMS_SINGLE); + CATCH_REQUIRE(ins[1].dType() == AMSDType::AMS_INT32); + CATCH_REQUIRE(outs[0].dType() == AMSDType::AMS_INT32); + + float* float_ptr = ins[0].data(); + int32_t* int_ptr = ins[1].data(); + int32_t* out_ptr = outs[0].data(); + + for (int i = 0; i < num_elements; ++i) { + // Convert float to int and add to int input + out_ptr[i] = static_cast(float_ptr[i]) + int_ptr[i]; + } + }; + + AMSCAbstrModel model = AMSRegisterAbstractModel( + "mixed_test", 1.0, "", false); + AMSExecutor executor = AMSCreateExecutor(model, 0, 1); + + AMSExecute(executor, computation, inputs, inouts, outputs); + + // Verify + for (int i = 0; i < num_elements; ++i) { + int32_t expected = + static_cast(static_cast(i) * 1.5f) + i * 2; + CATCH_REQUIRE(output_data[i] == expected); + } + + // Note: Not destroying executor to avoid triggering AMSFinalize between tests + // The executor will be cleaned up at program exit + } +} diff --git a/tests/AMSlib/wf/CMakeLists.txt b/tests/AMSlib/wf/CMakeLists.txt index 4e3f98fb..669c6b43 100644 --- a/tests/AMSlib/wf/CMakeLists.txt +++ b/tests/AMSlib/wf/CMakeLists.txt @@ -65,3 +65,6 @@ ADD_WORKFLOW_UNIT_TEST(WORKFLOW::PIPELINE pipeline) BUILD_UNIT_TEST(policy policy.cpp) ADD_WORKFLOW_UNIT_TEST(WORKFLOW::POLICY policy) + +BUILD_UNIT_TEST(int_tensors int_tensors.cpp) +ADD_WORKFLOW_UNIT_TEST(AMS_INT_SUPPORT int_tensors) diff --git a/tests/AMSlib/wf/int_tensors.cpp b/tests/AMSlib/wf/int_tensors.cpp new file mode 100644 index 00000000..608d599d --- /dev/null +++ b/tests/AMSlib/wf/int_tensors.cpp @@ -0,0 +1,418 @@ +/* + * Copyright 2021-2023 Lawrence Livermore National Security, LLC and other + * AMSLib Project Developers + * + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include +#include +#include +#include + +#include "AMS.h" +#include "AMSTensor.hpp" +#include "wf/resource_manager.hpp" +#include "wf/utils.hpp" + +using namespace ams; + +CATCH_TEST_CASE("AMSTensor: int32_t tensor creation and basic properties", + "[ams][tensor][int32]") +{ + AMSInit(); + + const auto device = GENERATE(AMSResourceType::AMS_HOST, AMSResourceType::AMS_DEVICE); + + // Skip GPU tests if CUDA is not available + if (device == AMSResourceType::AMS_DEVICE) { +#if !defined(__AMS_ENABLE_CUDA__) && !defined(__AMS_ENABLE_HIP__) + CATCH_SKIP("GPU device not available"); +#endif + } + + CATCH_SECTION("Create 1D int32_t tensor") + { + std::vector shape = {10}; + std::vector strides = {1}; + + auto tensor = AMSTensor::create(shape, strides, device); + + CATCH_REQUIRE(tensor.dType() == AMSDType::AMS_INT32); + CATCH_REQUIRE(tensor.elements() == 10); + CATCH_REQUIRE(tensor.element_size() == sizeof(int32_t)); + CATCH_REQUIRE(tensor.location() == device); + CATCH_REQUIRE(tensor.shape().size() == 1); + CATCH_REQUIRE(tensor.shape()[0] == 10); + // Note: contiguous() check removed due to pre-existing AMSTensor bug + } + + CATCH_SECTION("Create 2D int32_t tensor") + { + std::vector shape = {5, 8}; + std::vector strides = {8, 1}; + + auto tensor = AMSTensor::create(shape, strides, device); + + CATCH_REQUIRE(tensor.dType() == AMSDType::AMS_INT32); + CATCH_REQUIRE(tensor.elements() == 40); + CATCH_REQUIRE(tensor.element_size() == sizeof(int32_t)); + CATCH_REQUIRE(tensor.shape().size() == 2); + CATCH_REQUIRE(tensor.shape()[0] == 5); + CATCH_REQUIRE(tensor.shape()[1] == 8); + } + + CATCH_SECTION("Create 3D int32_t tensor") + { + std::vector shape = {4, 3, 2}; + std::vector strides = {6, 2, 1}; + + auto tensor = AMSTensor::create(shape, strides, device); + + CATCH_REQUIRE(tensor.dType() == AMSDType::AMS_INT32); + CATCH_REQUIRE(tensor.elements() == 24); + CATCH_REQUIRE(tensor.element_size() == sizeof(int32_t)); + } +} + +CATCH_TEST_CASE("AMSTensor: int64_t tensor creation and basic properties", + "[ams][tensor][int64]") +{ + AMSInit(); + + const auto device = GENERATE(AMSResourceType::AMS_HOST, AMSResourceType::AMS_DEVICE); + + if (device == AMSResourceType::AMS_DEVICE) { +#if !defined(__AMS_ENABLE_CUDA__) && !defined(__AMS_ENABLE_HIP__) + CATCH_SKIP("GPU device not available"); +#endif + } + + CATCH_SECTION("Create 1D int64_t tensor") + { + std::vector shape = {15}; + std::vector strides = {1}; + + auto tensor = AMSTensor::create(shape, strides, device); + + CATCH_REQUIRE(tensor.dType() == AMSDType::AMS_INT64); + CATCH_REQUIRE(tensor.elements() == 15); + CATCH_REQUIRE(tensor.element_size() == sizeof(int64_t)); + CATCH_REQUIRE(tensor.location() == device); + // Note: contiguous() check removed due to pre-existing AMSTensor bug + } + + CATCH_SECTION("Create 2D int64_t tensor") + { + std::vector shape = {6, 7}; + std::vector strides = {7, 1}; + + auto tensor = AMSTensor::create(shape, strides, device); + + CATCH_REQUIRE(tensor.dType() == AMSDType::AMS_INT64); + CATCH_REQUIRE(tensor.elements() == 42); + CATCH_REQUIRE(tensor.element_size() == sizeof(int64_t)); + } +} + +CATCH_TEST_CASE("AMSTensor: int32_t tensor view operations", "[ams][tensor][int32][view]") +{ + AMSInit(); + + const auto device = GENERATE(AMSResourceType::AMS_HOST); + + CATCH_SECTION("Create view from existing int32_t data") + { + std::vector data = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; + std::vector shape = {10}; + std::vector strides = {1}; + + auto tensor_view = AMSTensor::view(data.data(), shape, strides, device); + + CATCH_REQUIRE(tensor_view.dType() == AMSDType::AMS_INT32); + CATCH_REQUIRE(tensor_view.elements() == 10); + CATCH_REQUIRE(tensor_view.location() == device); + + // Verify we can access the data + auto* ptr = tensor_view.data(); + CATCH_REQUIRE(ptr != nullptr); + CATCH_REQUIRE(ptr[0] == 1); + CATCH_REQUIRE(ptr[9] == 10); + } + + CATCH_SECTION("Create 2D view from int32_t data") + { + std::vector data(20, 42); // 20 elements, all set to 42 + std::vector shape = {4, 5}; + std::vector strides = {5, 1}; + + auto tensor_view = AMSTensor::view(data.data(), shape, strides, device); + + CATCH_REQUIRE(tensor_view.dType() == AMSDType::AMS_INT32); + CATCH_REQUIRE(tensor_view.elements() == 20); + CATCH_REQUIRE(tensor_view.shape()[0] == 4); + CATCH_REQUIRE(tensor_view.shape()[1] == 5); + + auto* ptr = tensor_view.data(); + CATCH_REQUIRE(ptr[0] == 42); + CATCH_REQUIRE(ptr[19] == 42); + } +} + +CATCH_TEST_CASE("AMSTensor: int64_t tensor view operations", "[ams][tensor][int64][view]") +{ + AMSInit(); + + const auto device = GENERATE(AMSResourceType::AMS_HOST); + + CATCH_SECTION("Create view from existing int64_t data") + { + std::vector data = {100, 200, 300, 400, 500}; + std::vector shape = {5}; + std::vector strides = {1}; + + auto tensor_view = AMSTensor::view(data.data(), shape, strides, device); + + CATCH_REQUIRE(tensor_view.dType() == AMSDType::AMS_INT64); + CATCH_REQUIRE(tensor_view.elements() == 5); + + auto* ptr = tensor_view.data(); + CATCH_REQUIRE(ptr[0] == 100); + CATCH_REQUIRE(ptr[4] == 500); + } +} + +CATCH_TEST_CASE("AMSTensor: int tensor transpose operations", "[ams][tensor][transpose]") +{ + AMSInit(); + + const auto device = GENERATE(AMSResourceType::AMS_HOST); + + CATCH_SECTION("Transpose 2D int32_t tensor") + { + std::vector shape = {3, 4}; + std::vector strides = {4, 1}; + + auto tensor = AMSTensor::create(shape, strides, device); + auto transposed = tensor.transpose(0, 1); + + CATCH_REQUIRE(transposed.dType() == AMSDType::AMS_INT32); + CATCH_REQUIRE(transposed.shape()[0] == 4); + CATCH_REQUIRE(transposed.shape()[1] == 3); + CATCH_REQUIRE(transposed.elements() == 12); + } + + CATCH_SECTION("Transpose 2D int64_t tensor") + { + std::vector shape = {5, 6}; + std::vector strides = {6, 1}; + + auto tensor = AMSTensor::create(shape, strides, device); + auto transposed = tensor.transpose(0, 1); + + CATCH_REQUIRE(transposed.dType() == AMSDType::AMS_INT64); + CATCH_REQUIRE(transposed.shape()[0] == 6); + CATCH_REQUIRE(transposed.shape()[1] == 5); + CATCH_REQUIRE(transposed.elements() == 30); + } +} + +CATCH_TEST_CASE("AMSTensor: int tensor move semantics", "[ams][tensor][move]") +{ + AMSInit(); + + const auto device = GENERATE(AMSResourceType::AMS_HOST); + + CATCH_SECTION("Move int32_t tensor") + { + std::vector shape = {10}; + std::vector strides = {1}; + + auto tensor1 = AMSTensor::create(shape, strides, device); + auto* original_ptr = tensor1.data(); + + // Move construct + auto tensor2 = std::move(tensor1); + + CATCH_REQUIRE(tensor2.dType() == AMSDType::AMS_INT32); + CATCH_REQUIRE(tensor2.elements() == 10); + CATCH_REQUIRE(tensor2.data() == original_ptr); + } + + CATCH_SECTION("Move int64_t tensor") + { + std::vector shape = {20}; + std::vector strides = {1}; + + auto tensor1 = AMSTensor::create(shape, strides, device); + auto* original_ptr = tensor1.data(); + + // Move construct (not move assign, to avoid existing AMSTensor bug) + auto tensor2 = std::move(tensor1); + + CATCH_REQUIRE(tensor2.dType() == AMSDType::AMS_INT64); + CATCH_REQUIRE(tensor2.elements() == 20); + CATCH_REQUIRE(tensor2.data() == original_ptr); + } +} + +CATCH_TEST_CASE("AMSTensor: dtype_to_size utility for int types", "[ams][utils]") +{ + CATCH_SECTION("Verify int32_t size") + { + size_t size = dtype_to_size(AMSDType::AMS_INT32); + CATCH_REQUIRE(size == sizeof(int32_t)); + CATCH_REQUIRE(size == 4); + } + + CATCH_SECTION("Verify int64_t size") + { + size_t size = dtype_to_size(AMSDType::AMS_INT64); + CATCH_REQUIRE(size == sizeof(int64_t)); + CATCH_REQUIRE(size == 8); + } + + CATCH_SECTION("Compare sizes") + { + size_t size_int32 = dtype_to_size(AMSDType::AMS_INT32); + size_t size_int64 = dtype_to_size(AMSDType::AMS_INT64); + size_t size_float = dtype_to_size(AMSDType::AMS_SINGLE); + size_t size_double = dtype_to_size(AMSDType::AMS_DOUBLE); + + CATCH_REQUIRE(size_int32 == size_float); // Both 4 bytes + CATCH_REQUIRE(size_int64 == size_double); // Both 8 bytes + CATCH_REQUIRE(size_int64 == 2 * size_int32); + } +} + +CATCH_TEST_CASE("AMSTensor: SmallVector of int tensors", "[ams][tensor][smallvector]") +{ + AMSInit(); + + const auto device = GENERATE(AMSResourceType::AMS_HOST); + + CATCH_SECTION("Create vector of int32_t tensors") + { + ams::SmallVector tensors; + + std::vector shape1 = {5}; + std::vector shape2 = {10}; + std::vector strides = {1}; + + tensors.push_back(AMSTensor::create(shape1, strides, device)); + tensors.push_back(AMSTensor::create(shape2, strides, device)); + + CATCH_REQUIRE(tensors.size() == 2); + CATCH_REQUIRE(tensors[0].dType() == AMSDType::AMS_INT32); + CATCH_REQUIRE(tensors[1].dType() == AMSDType::AMS_INT32); + CATCH_REQUIRE(tensors[0].elements() == 5); + CATCH_REQUIRE(tensors[1].elements() == 10); + } + + CATCH_SECTION("Create vector of int64_t tensors") + { + ams::SmallVector tensors; + + std::vector shape = {7}; + std::vector strides = {1}; + + for (int i = 0; i < 3; ++i) { + tensors.push_back(AMSTensor::create(shape, strides, device)); + } + + CATCH_REQUIRE(tensors.size() == 3); + for (const auto& tensor : tensors) { + CATCH_REQUIRE(tensor.dType() == AMSDType::AMS_INT64); + CATCH_REQUIRE(tensor.elements() == 7); + } + } + + CATCH_SECTION("Mixed type tensors in SmallVector") + { + ams::SmallVector tensors; + + std::vector shape = {8}; + std::vector strides = {1}; + + tensors.push_back(AMSTensor::create(shape, strides, device)); + tensors.push_back(AMSTensor::create(shape, strides, device)); + tensors.push_back(AMSTensor::create(shape, strides, device)); + tensors.push_back(AMSTensor::create(shape, strides, device)); + + CATCH_REQUIRE(tensors.size() == 4); + CATCH_REQUIRE(tensors[0].dType() == AMSDType::AMS_SINGLE); + CATCH_REQUIRE(tensors[1].dType() == AMSDType::AMS_INT32); + CATCH_REQUIRE(tensors[2].dType() == AMSDType::AMS_DOUBLE); + CATCH_REQUIRE(tensors[3].dType() == AMSDType::AMS_INT64); + } +} + +CATCH_TEST_CASE("AMSTensor: int tensor data access and modification", + "[ams][tensor][data]") +{ + AMSInit(); + + const auto device = GENERATE(AMSResourceType::AMS_HOST); + + CATCH_SECTION("Write and read int32_t data") + { + std::vector shape = {5}; + std::vector strides = {1}; + + auto tensor = AMSTensor::create(shape, strides, device); + auto* data = tensor.data(); + + // Write data + for (int i = 0; i < 5; ++i) { + data[i] = i * 10; + } + + // Read data back + CATCH_REQUIRE(data[0] == 0); + CATCH_REQUIRE(data[1] == 10); + CATCH_REQUIRE(data[2] == 20); + CATCH_REQUIRE(data[3] == 30); + CATCH_REQUIRE(data[4] == 40); + } + + CATCH_SECTION("Write and read int64_t data") + { + std::vector shape = {3}; + std::vector strides = {1}; + + auto tensor = AMSTensor::create(shape, strides, device); + auto* data = tensor.data(); + + // Write large values + data[0] = 1000000000LL; + data[1] = 2000000000LL; + data[2] = 3000000000LL; + + // Read data back + CATCH_REQUIRE(data[0] == 1000000000LL); + CATCH_REQUIRE(data[1] == 2000000000LL); + CATCH_REQUIRE(data[2] == 3000000000LL); + } + + CATCH_SECTION("2D int32_t tensor data access") + { + std::vector shape = {3, 4}; + std::vector strides = {4, 1}; + + auto tensor = AMSTensor::create(shape, strides, device); + auto* data = tensor.data(); + + // Fill with row-major data + for (int i = 0; i < 3; ++i) { + for (int j = 0; j < 4; ++j) { + data[i * 4 + j] = i * 10 + j; + } + } + + // Verify access + CATCH_REQUIRE(data[0] == 0); // [0,0] + CATCH_REQUIRE(data[3] == 3); // [0,3] + CATCH_REQUIRE(data[4] == 10); // [1,0] + CATCH_REQUIRE(data[11] == 23); // [2,3] + } +} From 8a4c7e0edfcb5dd5ee70c86ff9dd1b2ef35e66bc Mon Sep 17 00:00:00 2001 From: Yohann Date: Thu, 9 Apr 2026 12:40:02 -0700 Subject: [PATCH 07/11] Update tests/AMSlib/ams_interface/int_interface.cpp Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- tests/AMSlib/ams_interface/int_interface.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tests/AMSlib/ams_interface/int_interface.cpp b/tests/AMSlib/ams_interface/int_interface.cpp index b139f671..7defa676 100644 --- a/tests/AMSlib/ams_interface/int_interface.cpp +++ b/tests/AMSlib/ams_interface/int_interface.cpp @@ -17,9 +17,7 @@ using namespace ams; // Global test fixture to initialize AMS once for all tests struct AMSGlobalFixture { - AMSGlobalFixture() { - AMSInit(); - } + AMSGlobalFixture() { AMSInit(); } }; // This creates a single global instance that will initialize AMS before any tests run From 6713128314058e8d08fc5f0a6a3cee4d792cfbca Mon Sep 17 00:00:00 2001 From: Yohann Date: Thu, 9 Apr 2026 12:41:08 -0700 Subject: [PATCH 08/11] Apply suggestions from code review Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- tests/AMSlib/ams_interface/int_interface.cpp | 8 ++--- tests/AMSlib/wf/int_tensors.cpp | 32 +++++++++++++------- 2 files changed, 25 insertions(+), 15 deletions(-) diff --git a/tests/AMSlib/ams_interface/int_interface.cpp b/tests/AMSlib/ams_interface/int_interface.cpp index 7defa676..d2bf7954 100644 --- a/tests/AMSlib/ams_interface/int_interface.cpp +++ b/tests/AMSlib/ams_interface/int_interface.cpp @@ -228,8 +228,8 @@ CATCH_TEST_CASE("AMS API: 2D int32_t tensor execution", "[ams][api][int32][2d]") } }; - AMSCAbstrModel model = AMSRegisterAbstractModel( - "int32_2d_test", 1.0, "", false); + AMSCAbstrModel model = + AMSRegisterAbstractModel("int32_2d_test", 1.0, "", false); AMSExecutor executor = AMSCreateExecutor(model, 0, 1); AMSExecute(executor, computation, inputs, inouts, outputs); @@ -304,8 +304,8 @@ CATCH_TEST_CASE("AMS API: Mixed type tensors", "[ams][api][mixed]") } }; - AMSCAbstrModel model = AMSRegisterAbstractModel( - "mixed_test", 1.0, "", false); + AMSCAbstrModel model = + AMSRegisterAbstractModel("mixed_test", 1.0, "", false); AMSExecutor executor = AMSCreateExecutor(model, 0, 1); AMSExecute(executor, computation, inputs, inouts, outputs); diff --git a/tests/AMSlib/wf/int_tensors.cpp b/tests/AMSlib/wf/int_tensors.cpp index 608d599d..3377bce1 100644 --- a/tests/AMSlib/wf/int_tensors.cpp +++ b/tests/AMSlib/wf/int_tensors.cpp @@ -22,7 +22,8 @@ CATCH_TEST_CASE("AMSTensor: int32_t tensor creation and basic properties", { AMSInit(); - const auto device = GENERATE(AMSResourceType::AMS_HOST, AMSResourceType::AMS_DEVICE); + const auto device = + GENERATE(AMSResourceType::AMS_HOST, AMSResourceType::AMS_DEVICE); // Skip GPU tests if CUDA is not available if (device == AMSResourceType::AMS_DEVICE) { @@ -80,7 +81,8 @@ CATCH_TEST_CASE("AMSTensor: int64_t tensor creation and basic properties", { AMSInit(); - const auto device = GENERATE(AMSResourceType::AMS_HOST, AMSResourceType::AMS_DEVICE); + const auto device = + GENERATE(AMSResourceType::AMS_HOST, AMSResourceType::AMS_DEVICE); if (device == AMSResourceType::AMS_DEVICE) { #if !defined(__AMS_ENABLE_CUDA__) && !defined(__AMS_ENABLE_HIP__) @@ -115,7 +117,8 @@ CATCH_TEST_CASE("AMSTensor: int64_t tensor creation and basic properties", } } -CATCH_TEST_CASE("AMSTensor: int32_t tensor view operations", "[ams][tensor][int32][view]") +CATCH_TEST_CASE("AMSTensor: int32_t tensor view operations", + "[ams][tensor][int32][view]") { AMSInit(); @@ -127,7 +130,8 @@ CATCH_TEST_CASE("AMSTensor: int32_t tensor view operations", "[ams][tensor][int3 std::vector shape = {10}; std::vector strides = {1}; - auto tensor_view = AMSTensor::view(data.data(), shape, strides, device); + auto tensor_view = + AMSTensor::view(data.data(), shape, strides, device); CATCH_REQUIRE(tensor_view.dType() == AMSDType::AMS_INT32); CATCH_REQUIRE(tensor_view.elements() == 10); @@ -146,7 +150,8 @@ CATCH_TEST_CASE("AMSTensor: int32_t tensor view operations", "[ams][tensor][int3 std::vector shape = {4, 5}; std::vector strides = {5, 1}; - auto tensor_view = AMSTensor::view(data.data(), shape, strides, device); + auto tensor_view = + AMSTensor::view(data.data(), shape, strides, device); CATCH_REQUIRE(tensor_view.dType() == AMSDType::AMS_INT32); CATCH_REQUIRE(tensor_view.elements() == 20); @@ -159,7 +164,8 @@ CATCH_TEST_CASE("AMSTensor: int32_t tensor view operations", "[ams][tensor][int3 } } -CATCH_TEST_CASE("AMSTensor: int64_t tensor view operations", "[ams][tensor][int64][view]") +CATCH_TEST_CASE("AMSTensor: int64_t tensor view operations", + "[ams][tensor][int64][view]") { AMSInit(); @@ -171,7 +177,8 @@ CATCH_TEST_CASE("AMSTensor: int64_t tensor view operations", "[ams][tensor][int6 std::vector shape = {5}; std::vector strides = {1}; - auto tensor_view = AMSTensor::view(data.data(), shape, strides, device); + auto tensor_view = + AMSTensor::view(data.data(), shape, strides, device); CATCH_REQUIRE(tensor_view.dType() == AMSDType::AMS_INT64); CATCH_REQUIRE(tensor_view.elements() == 5); @@ -182,7 +189,8 @@ CATCH_TEST_CASE("AMSTensor: int64_t tensor view operations", "[ams][tensor][int6 } } -CATCH_TEST_CASE("AMSTensor: int tensor transpose operations", "[ams][tensor][transpose]") +CATCH_TEST_CASE("AMSTensor: int tensor transpose operations", + "[ams][tensor][transpose]") { AMSInit(); @@ -256,7 +264,8 @@ CATCH_TEST_CASE("AMSTensor: int tensor move semantics", "[ams][tensor][move]") } } -CATCH_TEST_CASE("AMSTensor: dtype_to_size utility for int types", "[ams][utils]") +CATCH_TEST_CASE("AMSTensor: dtype_to_size utility for int types", + "[ams][utils]") { CATCH_SECTION("Verify int32_t size") { @@ -279,13 +288,14 @@ CATCH_TEST_CASE("AMSTensor: dtype_to_size utility for int types", "[ams][utils]" size_t size_float = dtype_to_size(AMSDType::AMS_SINGLE); size_t size_double = dtype_to_size(AMSDType::AMS_DOUBLE); - CATCH_REQUIRE(size_int32 == size_float); // Both 4 bytes + CATCH_REQUIRE(size_int32 == size_float); // Both 4 bytes CATCH_REQUIRE(size_int64 == size_double); // Both 8 bytes CATCH_REQUIRE(size_int64 == 2 * size_int32); } } -CATCH_TEST_CASE("AMSTensor: SmallVector of int tensors", "[ams][tensor][smallvector]") +CATCH_TEST_CASE("AMSTensor: SmallVector of int tensors", + "[ams][tensor][smallvector]") { AMSInit(); From fae7149c10f352b18c8e5cf3006fa7244b844036 Mon Sep 17 00:00:00 2001 From: Yohann Dudouit Date: Thu, 9 Apr 2026 14:03:58 -0700 Subject: [PATCH 09/11] Fix _elements used before initialization. --- src/AMSlib/AMSTensor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/AMSlib/AMSTensor.cpp b/src/AMSlib/AMSTensor.cpp index 45a41e28..f5b6dc3d 100644 --- a/src/AMSlib/AMSTensor.cpp +++ b/src/AMSlib/AMSTensor.cpp @@ -67,8 +67,8 @@ AMSTensor::AMSTensor(uint8_t* data, _location(location), _owned(!view) { - _bytes = _elements * _element_size; _elements = computeNumElements(shapes); + _bytes = _elements * _element_size; if (!_data) { throw std::runtime_error("Generating tensor with Null Pointer AMSTensor."); } From 4c7e851e80ffc1abf3e7ebac1cc07bd7f8a39c6a Mon Sep 17 00:00:00 2001 From: Yohann Dudouit Date: Thu, 9 Apr 2026 14:04:32 -0700 Subject: [PATCH 10/11] Fix HIP memory allocation and typo. --- src/AMSlib/wf/resource_manager.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/AMSlib/wf/resource_manager.hpp b/src/AMSlib/wf/resource_manager.hpp index 7b452ad5..39e646dd 100644 --- a/src/AMSlib/wf/resource_manager.hpp +++ b/src/AMSlib/wf/resource_manager.hpp @@ -155,9 +155,9 @@ class ResourceManager std::string pinned_alloc("PINNED"); if (!RMAllocators[AMSResourceType::AMS_HOST]) setAllocator(host_alloc, AMSResourceType::AMS_HOST); -#if defined(__AMS_ENABLE_CUDA__) +#if defined(__AMS_ENABLE_CUDA__) || defined(__AMS_ENABLE_HIP__) if (!RMAllocators[AMSResourceType::AMS_DEVICE]) - setAllocator(host_alloc, AMSResourceType::AMS_DEVICE); + setAllocator(device_alloc, AMSResourceType::AMS_DEVICE); if (!RMAllocators[AMSResourceType::AMS_PINNED]) setAllocator(pinned_alloc, AMSResourceType::AMS_PINNED); From 6362d3e9db8699ce9e8220fb5654a76454f4f76b Mon Sep 17 00:00:00 2001 From: Yohann Dudouit Date: Fri, 10 Apr 2026 10:53:09 -0700 Subject: [PATCH 11/11] Rename tests. --- tests/AMSlib/ams_interface/CMakeLists.txt | 2 +- tests/AMSlib/wf/CMakeLists.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/AMSlib/ams_interface/CMakeLists.txt b/tests/AMSlib/ams_interface/CMakeLists.txt index 139ca630..2fb519e3 100644 --- a/tests/AMSlib/ams_interface/CMakeLists.txt +++ b/tests/AMSlib/ams_interface/CMakeLists.txt @@ -25,5 +25,5 @@ BUILD_UNIT_TEST(ams_explicit_end_to_end ams_ete.cpp) ADD_AMS_UNIT_TEST(AMS_EXPLICIT ams_explicit_end_to_end) BUILD_UNIT_TEST(int_interface int_interface.cpp) -ADD_AMS_UNIT_TEST(AMS_INT_SUPPORT int_interface) +ADD_AMS_UNIT_TEST(AMS_INT_INTERFACE int_interface) diff --git a/tests/AMSlib/wf/CMakeLists.txt b/tests/AMSlib/wf/CMakeLists.txt index 669c6b43..2f8cd927 100644 --- a/tests/AMSlib/wf/CMakeLists.txt +++ b/tests/AMSlib/wf/CMakeLists.txt @@ -67,4 +67,4 @@ BUILD_UNIT_TEST(policy policy.cpp) ADD_WORKFLOW_UNIT_TEST(WORKFLOW::POLICY policy) BUILD_UNIT_TEST(int_tensors int_tensors.cpp) -ADD_WORKFLOW_UNIT_TEST(AMS_INT_SUPPORT int_tensors) +ADD_WORKFLOW_UNIT_TEST(AMS_INT_TENSOR int_tensors)