CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
3947 lines
185 KiB
C++
3947 lines
185 KiB
C++
/*******************************************************************************
|
|
*
|
|
* MIT License
|
|
*
|
|
* Copyright (C) 2022-2026 Advanced Micro Devices, Inc.
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
* of this software and associated documentation files (the "Software"), to deal
|
|
* in the Software without restriction, including without limitation the rights
|
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
* copies of the Software, and to permit persons to whom the Software is
|
|
* furnished to do so, subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be included in
|
|
* all copies or substantial portions of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
* SOFTWARE.
|
|
*
|
|
*******************************************************************************/
|
|
|
|
#pragma once
|
|
|
|
#include <hipblaslt/hipblaslt.h>
|
|
#include <hipblaslt/hipblaslt-ext-op.h>
|
|
#include <hipblaslt/hipblaslt-ext.hpp> // Add check for hipblaslt-ext
|
|
#include "hipblaslt_test.hpp"
|
|
#include "flops.hpp"
|
|
#include "hipblaslt_datatype2string.hpp"
|
|
#include "hipblaslt_init.hpp"
|
|
#include "hipblaslt_math.hpp"
|
|
#include "hipblaslt_random.hpp"
|
|
#include "hipblaslt_vector.hpp"
|
|
#ifdef CODE_COVERAGE
|
|
#include "check_numerics_matrix.hpp"
|
|
#include "hipblaslt_internal.hpp"
|
|
#include "rocblaslt_mat_utils.hpp"
|
|
#include "rocroller_host.hpp"
|
|
#include "status.h"
|
|
#include "tensile_host.hpp"
|
|
#include "utility.hpp"
|
|
#endif
|
|
#include "unit.hpp"
|
|
#include "utility.hpp"
|
|
|
|
void testing_aux_handle_init_bad_arg(const Arguments& arg)
|
|
{
|
|
EXPECT_HIPBLAS_STATUS(hipblasLtCreate(nullptr), HIPBLAS_STATUS_INVALID_VALUE);
|
|
}
|
|
|
|
void testing_aux_handle_destroy_bad_arg(const Arguments& arg)
|
|
{
|
|
EXPECT_HIPBLAS_STATUS(hipblasLtDestroy(nullptr), HIPBLAS_STATUS_INVALID_VALUE);
|
|
}
|
|
|
|
void testing_aux_handle(const Arguments& arg)
|
|
{
|
|
hipblasLtHandle_t handle;
|
|
EXPECT_HIPBLAS_STATUS(hipblasLtCreate(&handle), HIPBLAS_STATUS_SUCCESS);
|
|
EXPECT_HIPBLAS_STATUS(hipblasLtDestroy(handle), HIPBLAS_STATUS_SUCCESS);
|
|
}
|
|
|
|
void testing_aux_mat_init_bad_arg(const Arguments& arg)
|
|
{
|
|
const int64_t row = 128;
|
|
const int64_t col = 128;
|
|
const int64_t ld = 128;
|
|
|
|
hipblasLtMatrixLayout_t m_descr;
|
|
|
|
EXPECT_HIPBLAS_STATUS(hipblasLtMatrixLayoutCreate(nullptr, arg.a_type, row, col, ld),
|
|
HIPBLAS_STATUS_INVALID_VALUE);
|
|
}
|
|
|
|
void testing_aux_mat_init(const Arguments& arg)
|
|
{
|
|
const int64_t row = 128;
|
|
const int64_t col = 128;
|
|
const int64_t ld = 128;
|
|
|
|
hipblaslt_local_handle handle{arg};
|
|
hipblaslt_local_matrix_layout mat(row, col, ld, arg.a_type);
|
|
EXPECT_HIPBLAS_STATUS(mat.status(), HIPBLAS_STATUS_SUCCESS);
|
|
}
|
|
|
|
void testing_aux_mat_destroy_bad_arg(const Arguments& arg)
|
|
{
|
|
EXPECT_HIPBLAS_STATUS(hipblasLtMatrixLayoutDestroy(nullptr), HIPBLAS_STATUS_INVALID_VALUE);
|
|
}
|
|
|
|
void testing_aux_mat_set_attr_bad_arg(const Arguments& arg)
|
|
{
|
|
const int64_t row = 128;
|
|
const int64_t col = 128;
|
|
const int64_t ld = 128;
|
|
|
|
int32_t data32;
|
|
int64_t data64;
|
|
uint32_t udata32;
|
|
uint64_t udata64;
|
|
|
|
hipblaslt_local_matrix_layout mat(row, col, ld, arg.a_type);
|
|
EXPECT_HIPBLAS_STATUS(mat.status(), HIPBLAS_STATUS_SUCCESS);
|
|
// Test with null matrix layout
|
|
EXPECT_HIPBLAS_STATUS(
|
|
hipblasLtMatrixLayoutSetAttribute(
|
|
nullptr, HIPBLASLT_MATRIX_LAYOUT_BATCH_COUNT, &data32, sizeof(int32_t)),
|
|
HIPBLAS_STATUS_NOT_INITIALIZED);
|
|
|
|
EXPECT_HIPBLAS_STATUS(hipblasLtMatrixLayoutSetAttribute(
|
|
mat, HIPBLASLT_MATRIX_LAYOUT_BATCH_COUNT, nullptr, sizeof(int32_t)),
|
|
HIPBLAS_STATUS_INVALID_VALUE);
|
|
|
|
// Test with zero size
|
|
EXPECT_HIPBLAS_STATUS(
|
|
hipblasLtMatrixLayoutSetAttribute(mat, HIPBLASLT_MATRIX_LAYOUT_BATCH_COUNT, &data32, 0),
|
|
HIPBLAS_STATUS_INVALID_VALUE);
|
|
|
|
// Test HIPBLASLT_MATRIX_LAYOUT_BATCH_COUNT with insufficient buffer size
|
|
data32 = 1;
|
|
EXPECT_HIPBLAS_STATUS(
|
|
hipblasLtMatrixLayoutSetAttribute(
|
|
mat, HIPBLASLT_MATRIX_LAYOUT_BATCH_COUNT, &data32, sizeof(int32_t) / 2),
|
|
HIPBLAS_STATUS_INVALID_VALUE);
|
|
|
|
EXPECT_HIPBLAS_STATUS(
|
|
hipblasLtMatrixLayoutSetAttribute(mat, HIPBLASLT_MATRIX_LAYOUT_BATCH_COUNT, &data32, 1),
|
|
HIPBLAS_STATUS_INVALID_VALUE);
|
|
|
|
// Test HIPBLASLT_MATRIX_LAYOUT_STRIDED_BATCH_OFFSET with insufficient buffer size
|
|
data64 = ld * col;
|
|
EXPECT_HIPBLAS_STATUS(
|
|
hipblasLtMatrixLayoutSetAttribute(
|
|
mat, HIPBLASLT_MATRIX_LAYOUT_STRIDED_BATCH_OFFSET, &data64, sizeof(int64_t) / 2),
|
|
HIPBLAS_STATUS_INVALID_VALUE);
|
|
|
|
EXPECT_HIPBLAS_STATUS(hipblasLtMatrixLayoutSetAttribute(
|
|
mat, HIPBLASLT_MATRIX_LAYOUT_STRIDED_BATCH_OFFSET, &data64, 1),
|
|
HIPBLAS_STATUS_INVALID_VALUE);
|
|
|
|
EXPECT_HIPBLAS_STATUS(
|
|
hipblasLtMatrixLayoutSetAttribute(
|
|
mat, HIPBLASLT_MATRIX_LAYOUT_STRIDED_BATCH_OFFSET, nullptr, sizeof(int64_t)),
|
|
HIPBLAS_STATUS_INVALID_VALUE);
|
|
|
|
// Test HIPBLASLT_MATRIX_LAYOUT_TYPE with insufficient buffer size
|
|
udata32 = static_cast<uint32_t>(arg.a_type);
|
|
EXPECT_HIPBLAS_STATUS(hipblasLtMatrixLayoutSetAttribute(
|
|
mat, HIPBLASLT_MATRIX_LAYOUT_TYPE, &udata32, sizeof(uint32_t) / 2),
|
|
HIPBLAS_STATUS_INVALID_VALUE);
|
|
|
|
EXPECT_HIPBLAS_STATUS(
|
|
hipblasLtMatrixLayoutSetAttribute(mat, HIPBLASLT_MATRIX_LAYOUT_TYPE, &udata32, 1),
|
|
HIPBLAS_STATUS_INVALID_VALUE);
|
|
|
|
EXPECT_HIPBLAS_STATUS(hipblasLtMatrixLayoutSetAttribute(
|
|
mat, HIPBLASLT_MATRIX_LAYOUT_TYPE, nullptr, sizeof(uint32_t)),
|
|
HIPBLAS_STATUS_INVALID_VALUE);
|
|
|
|
// Test HIPBLASLT_MATRIX_LAYOUT_ORDER with insufficient buffer size
|
|
data32 = HIPBLASLT_ORDER_COL;
|
|
EXPECT_HIPBLAS_STATUS(hipblasLtMatrixLayoutSetAttribute(
|
|
mat, HIPBLASLT_MATRIX_LAYOUT_ORDER, &data32, sizeof(int32_t) / 2),
|
|
HIPBLAS_STATUS_INVALID_VALUE);
|
|
|
|
EXPECT_HIPBLAS_STATUS(
|
|
hipblasLtMatrixLayoutSetAttribute(mat, HIPBLASLT_MATRIX_LAYOUT_ORDER, &data32, 1),
|
|
HIPBLAS_STATUS_INVALID_VALUE);
|
|
|
|
EXPECT_HIPBLAS_STATUS(hipblasLtMatrixLayoutSetAttribute(
|
|
mat, HIPBLASLT_MATRIX_LAYOUT_ORDER, nullptr, sizeof(int32_t)),
|
|
HIPBLAS_STATUS_INVALID_VALUE);
|
|
|
|
// Test HIPBLASLT_MATRIX_LAYOUT_ROWS with insufficient buffer size
|
|
udata64 = static_cast<uint64_t>(row);
|
|
EXPECT_HIPBLAS_STATUS(hipblasLtMatrixLayoutSetAttribute(
|
|
mat, HIPBLASLT_MATRIX_LAYOUT_ROWS, &udata64, sizeof(uint64_t) / 2),
|
|
HIPBLAS_STATUS_INVALID_VALUE);
|
|
|
|
EXPECT_HIPBLAS_STATUS(
|
|
hipblasLtMatrixLayoutSetAttribute(mat, HIPBLASLT_MATRIX_LAYOUT_ROWS, &udata64, 1),
|
|
HIPBLAS_STATUS_INVALID_VALUE);
|
|
|
|
EXPECT_HIPBLAS_STATUS(hipblasLtMatrixLayoutSetAttribute(
|
|
mat, HIPBLASLT_MATRIX_LAYOUT_ROWS, nullptr, sizeof(uint64_t)),
|
|
HIPBLAS_STATUS_INVALID_VALUE);
|
|
|
|
// Test HIPBLASLT_MATRIX_LAYOUT_COLS with insufficient buffer size
|
|
udata64 = static_cast<uint64_t>(col);
|
|
EXPECT_HIPBLAS_STATUS(hipblasLtMatrixLayoutSetAttribute(
|
|
mat, HIPBLASLT_MATRIX_LAYOUT_COLS, &udata64, sizeof(uint64_t) / 2),
|
|
HIPBLAS_STATUS_INVALID_VALUE);
|
|
|
|
EXPECT_HIPBLAS_STATUS(
|
|
hipblasLtMatrixLayoutSetAttribute(mat, HIPBLASLT_MATRIX_LAYOUT_COLS, &udata64, 1),
|
|
HIPBLAS_STATUS_INVALID_VALUE);
|
|
|
|
EXPECT_HIPBLAS_STATUS(hipblasLtMatrixLayoutSetAttribute(
|
|
mat, HIPBLASLT_MATRIX_LAYOUT_COLS, nullptr, sizeof(uint64_t)),
|
|
HIPBLAS_STATUS_INVALID_VALUE);
|
|
|
|
// Test HIPBLASLT_MATRIX_LAYOUT_LD with insufficient buffer size
|
|
data64 = ld;
|
|
EXPECT_HIPBLAS_STATUS(hipblasLtMatrixLayoutSetAttribute(
|
|
mat, HIPBLASLT_MATRIX_LAYOUT_LD, &data64, sizeof(int64_t) / 2),
|
|
HIPBLAS_STATUS_INVALID_VALUE);
|
|
|
|
EXPECT_HIPBLAS_STATUS(
|
|
hipblasLtMatrixLayoutSetAttribute(mat, HIPBLASLT_MATRIX_LAYOUT_LD, &data64, 1),
|
|
HIPBLAS_STATUS_INVALID_VALUE);
|
|
|
|
EXPECT_HIPBLAS_STATUS(hipblasLtMatrixLayoutSetAttribute(
|
|
mat, HIPBLASLT_MATRIX_LAYOUT_LD, nullptr, sizeof(int64_t)),
|
|
HIPBLAS_STATUS_INVALID_VALUE);
|
|
|
|
// Test with invalid attribute (assuming there's a MAX value for bounds checking)
|
|
EXPECT_HIPBLAS_STATUS(
|
|
hipblasLtMatrixLayoutSetAttribute(
|
|
mat, static_cast<hipblasLtMatrixLayoutAttribute_t>(999), &data32, sizeof(int32_t)),
|
|
HIPBLAS_STATUS_INVALID_VALUE);
|
|
}
|
|
|
|
void testing_aux_mat_get_attr_bad_arg(const Arguments& arg)
|
|
{
|
|
const int64_t row = 128;
|
|
const int64_t col = 128;
|
|
const int64_t ld = 128;
|
|
|
|
hipblaslt_local_matrix_layout mat(row, col, ld, arg.a_type);
|
|
EXPECT_HIPBLAS_STATUS(mat.status(), HIPBLAS_STATUS_SUCCESS);
|
|
|
|
int data;
|
|
int64_t data64;
|
|
size_t sizeWritten;
|
|
|
|
EXPECT_HIPBLAS_STATUS(
|
|
hipblasLtMatrixLayoutGetAttribute(
|
|
nullptr, HIPBLASLT_MATRIX_LAYOUT_BATCH_COUNT, &data, sizeof(int), &sizeWritten),
|
|
HIPBLAS_STATUS_NOT_INITIALIZED);
|
|
|
|
EXPECT_HIPBLAS_STATUS(
|
|
hipblasLtMatrixLayoutGetAttribute(
|
|
mat, HIPBLASLT_MATRIX_LAYOUT_BATCH_COUNT, nullptr, sizeof(int), &sizeWritten),
|
|
HIPBLAS_STATUS_INVALID_VALUE);
|
|
|
|
EXPECT_HIPBLAS_STATUS(hipblasLtMatrixLayoutGetAttribute(
|
|
mat, HIPBLASLT_MATRIX_LAYOUT_BATCH_COUNT, nullptr, 0, nullptr),
|
|
HIPBLAS_STATUS_INVALID_VALUE);
|
|
|
|
EXPECT_HIPBLAS_STATUS(hipblasLtMatrixLayoutGetAttribute(
|
|
mat, HIPBLASLT_MATRIX_LAYOUT_BATCH_COUNT, &data, 1, &sizeWritten),
|
|
HIPBLAS_STATUS_INVALID_VALUE);
|
|
EXPECT_HIPBLAS_STATUS(
|
|
hipblasLtMatrixLayoutGetAttribute(mat,
|
|
HIPBLASLT_MATRIX_LAYOUT_STRIDED_BATCH_OFFSET,
|
|
nullptr,
|
|
sizeof(int64_t),
|
|
&sizeWritten),
|
|
HIPBLAS_STATUS_INVALID_VALUE);
|
|
EXPECT_HIPBLAS_STATUS(
|
|
hipblasLtMatrixLayoutGetAttribute(
|
|
mat, HIPBLASLT_MATRIX_LAYOUT_STRIDED_BATCH_OFFSET, &data64, sizeof(int), &sizeWritten),
|
|
HIPBLAS_STATUS_INVALID_VALUE);
|
|
// test sizeWritten is nullptr, and the return state should be success
|
|
data = 0;
|
|
EXPECT_HIPBLAS_STATUS(
|
|
hipblasLtMatrixLayoutGetAttribute(
|
|
mat, HIPBLASLT_MATRIX_LAYOUT_BATCH_COUNT, &data, sizeof(int), nullptr),
|
|
HIPBLAS_STATUS_SUCCESS);
|
|
EXPECT_EQ(data, 1);
|
|
}
|
|
|
|
void testing_aux_mat_set_get_attr(const Arguments& arg)
|
|
{
|
|
const int64_t row = 128;
|
|
const int64_t col = 128;
|
|
const int64_t ld = 128;
|
|
|
|
hipblaslt_local_matrix_layout mat(row, col, ld, arg.a_type);
|
|
EXPECT_HIPBLAS_STATUS(mat.status(), HIPBLAS_STATUS_SUCCESS);
|
|
|
|
int32_t data, data_r;
|
|
size_t sizeWritten;
|
|
|
|
data = 2;
|
|
EXPECT_HIPBLAS_STATUS(hipblasLtMatrixLayoutSetAttribute(
|
|
mat, HIPBLASLT_MATRIX_LAYOUT_BATCH_COUNT, &data, sizeof(data)),
|
|
HIPBLAS_STATUS_SUCCESS);
|
|
|
|
EXPECT_HIPBLAS_STATUS(
|
|
hipblasLtMatrixLayoutGetAttribute(
|
|
mat, HIPBLASLT_MATRIX_LAYOUT_BATCH_COUNT, &data_r, sizeof(data), &sizeWritten),
|
|
HIPBLAS_STATUS_SUCCESS);
|
|
ASSERT_TRUE(data_r == data);
|
|
|
|
std::vector<int64_t> data64_v = {0, ld * col};
|
|
int64_t data64_r = 0;
|
|
for(int64_t data64 : data64_v)
|
|
{
|
|
EXPECT_HIPBLAS_STATUS(
|
|
hipblasLtMatrixLayoutSetAttribute(
|
|
mat, HIPBLASLT_MATRIX_LAYOUT_STRIDED_BATCH_OFFSET, &data64, sizeof(int64_t)),
|
|
HIPBLAS_STATUS_SUCCESS);
|
|
|
|
EXPECT_HIPBLAS_STATUS(
|
|
hipblasLtMatrixLayoutGetAttribute(mat,
|
|
HIPBLASLT_MATRIX_LAYOUT_STRIDED_BATCH_OFFSET,
|
|
&data64_r,
|
|
sizeof(int64_t),
|
|
&sizeWritten),
|
|
HIPBLAS_STATUS_SUCCESS);
|
|
ASSERT_TRUE(data64_r == data64);
|
|
}
|
|
}
|
|
|
|
void testing_aux_matmul_init_bad_arg(const Arguments& arg)
|
|
{
|
|
EXPECT_HIPBLAS_STATUS(hipblasLtMatmulDescCreate(nullptr, arg.compute_type, arg.scale_type),
|
|
HIPBLAS_STATUS_INVALID_VALUE);
|
|
}
|
|
|
|
void testing_aux_matmul_init(const Arguments& arg)
|
|
{
|
|
const hipblasOperation_t opA = HIPBLAS_OP_T;
|
|
const hipblasOperation_t opB = HIPBLAS_OP_N;
|
|
|
|
hipblaslt_local_matmul_descr matmul(opA, opB, arg.compute_type, arg.scale_type);
|
|
EXPECT_HIPBLAS_STATUS(matmul.status(), HIPBLAS_STATUS_SUCCESS);
|
|
}
|
|
|
|
void testing_aux_matmul_set_attr_bad_arg(const Arguments& arg)
|
|
{
|
|
const hipblasOperation_t opA = HIPBLAS_OP_T;
|
|
const hipblasOperation_t opB = HIPBLAS_OP_N;
|
|
|
|
hipblaslt_local_matmul_descr matmul(opA, opB, arg.compute_type, arg.scale_type);
|
|
EXPECT_HIPBLAS_STATUS(matmul.status(), HIPBLAS_STATUS_SUCCESS);
|
|
|
|
hipblasLtEpilogue_t data = HIPBLASLT_EPILOGUE_RELU;
|
|
EXPECT_HIPBLAS_STATUS(hipblasLtMatmulDescSetAttribute(
|
|
nullptr, HIPBLASLT_MATMUL_DESC_EPILOGUE, &data, sizeof(data)),
|
|
HIPBLAS_STATUS_NOT_INITIALIZED);
|
|
|
|
EXPECT_HIPBLAS_STATUS(hipblasLtMatmulDescSetAttribute(
|
|
matmul, HIPBLASLT_MATMUL_DESC_EPILOGUE, nullptr, sizeof(data)),
|
|
HIPBLAS_STATUS_INVALID_VALUE);
|
|
EXPECT_HIPBLAS_STATUS(
|
|
hipblasLtMatmulDescSetAttribute(matmul, HIPBLASLT_MATMUL_DESC_EPILOGUE, &data, 1),
|
|
HIPBLAS_STATUS_INVALID_VALUE);
|
|
}
|
|
|
|
void testing_aux_matmul_get_attr_bad_arg(const Arguments& arg)
|
|
{
|
|
const hipblasOperation_t opA = HIPBLAS_OP_T;
|
|
const hipblasOperation_t opB = HIPBLAS_OP_N;
|
|
|
|
hipblaslt_local_matmul_descr matmul(opA, opB, arg.compute_type, arg.scale_type);
|
|
EXPECT_HIPBLAS_STATUS(matmul.status(), HIPBLAS_STATUS_SUCCESS);
|
|
|
|
hipblasLtEpilogue_t data = HIPBLASLT_EPILOGUE_RELU;
|
|
size_t sizeWritten;
|
|
EXPECT_HIPBLAS_STATUS(
|
|
hipblasLtMatmulDescGetAttribute(
|
|
nullptr, HIPBLASLT_MATMUL_DESC_EPILOGUE, &data, sizeof(data), &sizeWritten),
|
|
HIPBLAS_STATUS_NOT_INITIALIZED);
|
|
|
|
EXPECT_HIPBLAS_STATUS(
|
|
hipblasLtMatmulDescGetAttribute(
|
|
matmul, HIPBLASLT_MATMUL_DESC_EPILOGUE, nullptr, sizeof(data), &sizeWritten),
|
|
HIPBLAS_STATUS_INVALID_VALUE);
|
|
EXPECT_HIPBLAS_STATUS(hipblasLtMatmulDescGetAttribute(
|
|
matmul, HIPBLASLT_MATMUL_DESC_EPILOGUE, &data, 1, &sizeWritten),
|
|
HIPBLAS_STATUS_INVALID_VALUE);
|
|
|
|
void* dBias = nullptr;
|
|
EXPECT_HIPBLAS_STATUS(hipblasLtMatmulDescGetAttribute(
|
|
matmul, HIPBLASLT_MATMUL_DESC_BIAS_POINTER, &dBias, 4, &sizeWritten),
|
|
HIPBLAS_STATUS_INVALID_VALUE);
|
|
// test sizeWritten is nullptr, and the return state should be success
|
|
data = HIPBLASLT_EPILOGUE_RELU;
|
|
EXPECT_HIPBLAS_STATUS(hipblasLtMatmulDescGetAttribute(
|
|
matmul, HIPBLASLT_MATMUL_DESC_EPILOGUE, &data, sizeof(data), nullptr),
|
|
HIPBLAS_STATUS_SUCCESS);
|
|
// test return buffer value equals HIPBLASLT_EPILOGUE_DEFAULT
|
|
EXPECT_EQ(data, HIPBLASLT_EPILOGUE_DEFAULT);
|
|
}
|
|
|
|
void testing_aux_matmul_set_get_attr(const Arguments& arg)
|
|
{
|
|
size_t sizeWritten;
|
|
hipblasLtMatmulDesc_t matmul;
|
|
CHECK_HIPBLASLT_ERROR(hipblasLtMatmulDescCreate(&matmul, arg.compute_type, arg.scale_type));
|
|
int64_t m = 1;
|
|
int64_t n = 1;
|
|
int64_t k = 1;
|
|
|
|
// For HIPBLASLT_MATMUL_DESC_TRANSA
|
|
hipblasOperation_t transA = HIPBLAS_OP_T;
|
|
hipblasOperation_t transA_r = HIPBLAS_OP_N;
|
|
|
|
EXPECT_HIPBLAS_STATUS(
|
|
hipblasLtMatmulDescSetAttribute(matmul, HIPBLASLT_MATMUL_DESC_TRANSA, &transA, 0),
|
|
HIPBLAS_STATUS_INVALID_VALUE); // edge case
|
|
|
|
EXPECT_HIPBLAS_STATUS(hipblasLtMatmulDescSetAttribute(
|
|
matmul, HIPBLASLT_MATMUL_DESC_TRANSA, &transA, sizeof(int32_t) / 2),
|
|
HIPBLAS_STATUS_INVALID_VALUE); // edge case
|
|
|
|
EXPECT_HIPBLAS_STATUS(hipblasLtMatmulDescSetAttribute(
|
|
matmul, HIPBLASLT_MATMUL_DESC_TRANSA, &transA, sizeof(int32_t)),
|
|
HIPBLAS_STATUS_SUCCESS); // normal case
|
|
|
|
EXPECT_HIPBLAS_STATUS(hipblasLtMatmulDescGetAttribute(
|
|
matmul, HIPBLASLT_MATMUL_DESC_BIAS_POINTER, &transA_r, 0, nullptr),
|
|
HIPBLASLT_MATMUL_DESC_BIAS_POINTER); // edge case
|
|
|
|
EXPECT_HIPBLAS_STATUS(
|
|
hipblasLtMatmulDescGetAttribute(
|
|
matmul, HIPBLASLT_MATMUL_DESC_TRANSA, &transA_r, sizeof(transA_r) / 2, &sizeWritten),
|
|
HIPBLAS_STATUS_INVALID_VALUE); // edge case
|
|
|
|
EXPECT_HIPBLAS_STATUS(
|
|
hipblasLtMatmulDescGetAttribute(
|
|
matmul, HIPBLASLT_MATMUL_DESC_TRANSA, &transA_r, sizeof(transA_r), &sizeWritten),
|
|
HIPBLAS_STATUS_SUCCESS); // normal case
|
|
|
|
ASSERT_TRUE(transA_r == transA); // validate
|
|
|
|
// For HIPBLASLT_MATMUL_DESC_TRANSB
|
|
|
|
hipblasOperation_t transB = HIPBLAS_OP_N;
|
|
hipblasOperation_t transB_r = HIPBLAS_OP_T;
|
|
|
|
EXPECT_HIPBLAS_STATUS(hipblasLtMatmulDescSetAttribute(
|
|
matmul, HIPBLASLT_MATMUL_DESC_TRANSB, &transB, sizeof(int32_t) / 2),
|
|
HIPBLAS_STATUS_INVALID_VALUE); // edge case
|
|
|
|
EXPECT_HIPBLAS_STATUS(hipblasLtMatmulDescSetAttribute(
|
|
matmul, HIPBLASLT_MATMUL_DESC_TRANSB, &transB, sizeof(int32_t)),
|
|
HIPBLAS_STATUS_SUCCESS); // normal case
|
|
|
|
EXPECT_HIPBLAS_STATUS(
|
|
hipblasLtMatmulDescGetAttribute(
|
|
matmul, HIPBLASLT_MATMUL_DESC_TRANSB, &transB_r, sizeof(transB_r) / 2, &sizeWritten),
|
|
HIPBLAS_STATUS_INVALID_VALUE); // edge case
|
|
|
|
EXPECT_HIPBLAS_STATUS(
|
|
hipblasLtMatmulDescGetAttribute(
|
|
matmul, HIPBLASLT_MATMUL_DESC_TRANSB, &transB_r, sizeof(transB_r), &sizeWritten),
|
|
HIPBLAS_STATUS_SUCCESS); // normal case
|
|
|
|
ASSERT_TRUE(transB_r == transB); // validate
|
|
|
|
// for HIPBLASLT_MATMUL_DESC_EPILOGUE
|
|
hipblasLtEpilogue_t data = HIPBLASLT_EPILOGUE_DEFAULT;
|
|
hipblasLtEpilogue_t data_r = HIPBLASLT_EPILOGUE_RELU;
|
|
EXPECT_HIPBLAS_STATUS(hipblasLtMatmulDescSetAttribute(
|
|
matmul, HIPBLASLT_MATMUL_DESC_EPILOGUE, &data, sizeof(data)),
|
|
HIPBLAS_STATUS_SUCCESS);
|
|
EXPECT_HIPBLAS_STATUS(
|
|
hipblasLtMatmulDescGetAttribute(
|
|
matmul, HIPBLASLT_MATMUL_DESC_EPILOGUE, &data_r, sizeof(data_r), &sizeWritten),
|
|
HIPBLAS_STATUS_SUCCESS);
|
|
ASSERT_TRUE(data_r == data);
|
|
|
|
// for HIPBLASLT_MATMUL_DESC_BIAS_POINTER set and get
|
|
void* d_bias;
|
|
void* d_bias_r;
|
|
CHECK_HIP_ERROR(hipMalloc(&d_bias, k * sizeof(hipblasLtHalf)));
|
|
|
|
EXPECT_HIPBLAS_STATUS(
|
|
hipblasLtMatmulDescSetAttribute(
|
|
matmul, HIPBLASLT_MATMUL_DESC_BIAS_POINTER, &d_bias, sizeof(void*) / 2),
|
|
HIPBLAS_STATUS_INVALID_VALUE);
|
|
|
|
EXPECT_HIPBLAS_STATUS(hipblasLtMatmulDescSetAttribute(
|
|
matmul, HIPBLASLT_MATMUL_DESC_BIAS_POINTER, &d_bias, sizeof(void*)),
|
|
HIPBLAS_STATUS_SUCCESS);
|
|
|
|
EXPECT_HIPBLAS_STATUS(
|
|
hipblasLtMatmulDescGetAttribute(
|
|
matmul, HIPBLASLT_MATMUL_DESC_BIAS_POINTER, &d_bias_r, sizeof(d_bias_r), &sizeWritten),
|
|
HIPBLAS_STATUS_SUCCESS);
|
|
|
|
ASSERT_TRUE(d_bias_r == d_bias);
|
|
|
|
// for HIPBLASLT_MATMUL_DESC_A_SCALE_POINTER
|
|
// We create a new matmul_descr becasue we don't want to set matmulDesc->scaleAType as Scalar in advance.
|
|
// If we set it as Scalar, it will skip some cases, which is not what we desire for.
|
|
const hipblasOperation_t opA = HIPBLAS_OP_T;
|
|
const hipblasOperation_t opB = HIPBLAS_OP_N;
|
|
|
|
hipblaslt_local_matmul_descr matmul_descr(opA, opB, arg.compute_type, arg.scale_type);
|
|
EXPECT_HIPBLAS_STATUS(matmul_descr.status(), HIPBLAS_STATUS_SUCCESS);
|
|
|
|
float h_scale_a_for_desc_a_scale_pointer = 2.f; // Example scale value, adjust as needed
|
|
float* d_scale_a;
|
|
float* d_scale_a_r;
|
|
CHECK_HIP_ERROR(hipMalloc(&d_scale_a, sizeof(float)));
|
|
CHECK_HIP_ERROR(hipMemcpy(
|
|
d_scale_a, &h_scale_a_for_desc_a_scale_pointer, sizeof(float), hipMemcpyHostToDevice));
|
|
|
|
EXPECT_HIPBLAS_STATUS(
|
|
hipblasLtMatmulDescSetAttribute(
|
|
matmul_descr, HIPBLASLT_MATMUL_DESC_A_SCALE_POINTER, &d_scale_a, sizeof(float*) / 2),
|
|
HIPBLAS_STATUS_INVALID_VALUE);
|
|
|
|
EXPECT_HIPBLAS_STATUS(
|
|
hipblasLtMatmulDescSetAttribute(
|
|
matmul_descr, HIPBLASLT_MATMUL_DESC_A_SCALE_POINTER, &d_scale_a, sizeof(float*)),
|
|
HIPBLAS_STATUS_SUCCESS);
|
|
|
|
EXPECT_HIPBLAS_STATUS(hipblasLtMatmulDescGetAttribute(matmul_descr,
|
|
HIPBLASLT_MATMUL_DESC_A_SCALE_POINTER,
|
|
&d_scale_a_r,
|
|
sizeof(float*) / 2,
|
|
&sizeWritten),
|
|
HIPBLAS_STATUS_INVALID_VALUE);
|
|
|
|
EXPECT_HIPBLAS_STATUS(hipblasLtMatmulDescGetAttribute(matmul_descr,
|
|
HIPBLASLT_MATMUL_DESC_A_SCALE_POINTER,
|
|
&d_scale_a_r,
|
|
sizeof(float*),
|
|
&sizeWritten),
|
|
HIPBLAS_STATUS_SUCCESS);
|
|
ASSERT_TRUE(d_scale_a_r == d_scale_a); // validate
|
|
|
|
// HIPBLASLT_MATMUL_DESC_A_SCALE_MODE
|
|
|
|
hipblasLtMatmulMatrixScale_t scale_mode_a = HIPBLASLT_MATMUL_MATRIX_SCALE_VEC32_UE8M0;
|
|
hipblasLtMatmulMatrixScale_t scale_mode_a_r = HIPBLASLT_MATMUL_MATRIX_SCALE_END;
|
|
|
|
EXPECT_HIPBLAS_STATUS(hipblasLtMatmulDescGetAttribute(matmul,
|
|
HIPBLASLT_MATMUL_DESC_A_SCALE_MODE,
|
|
&scale_mode_a_r,
|
|
sizeof(uint32_t),
|
|
&sizeWritten),
|
|
HIPBLAS_STATUS_INVALID_VALUE); // we didn't set it yet, so we get error
|
|
|
|
EXPECT_HIPBLAS_STATUS(
|
|
hipblasLtMatmulDescSetAttribute(
|
|
matmul, HIPBLASLT_MATMUL_DESC_A_SCALE_MODE, &scale_mode_a, sizeof(uint32_t) / 2),
|
|
HIPBLAS_STATUS_INVALID_VALUE);
|
|
|
|
EXPECT_HIPBLAS_STATUS(
|
|
hipblasLtMatmulDescSetAttribute(
|
|
matmul, HIPBLASLT_MATMUL_DESC_A_SCALE_MODE, &scale_mode_a, sizeof(uint32_t)),
|
|
HIPBLAS_STATUS_SUCCESS);
|
|
|
|
EXPECT_HIPBLAS_STATUS(hipblasLtMatmulDescGetAttribute(matmul,
|
|
HIPBLASLT_MATMUL_DESC_A_SCALE_MODE,
|
|
&scale_mode_a_r,
|
|
sizeof(uint32_t) / 2,
|
|
&sizeWritten),
|
|
HIPBLAS_STATUS_INVALID_VALUE);
|
|
|
|
EXPECT_HIPBLAS_STATUS(hipblasLtMatmulDescGetAttribute(matmul,
|
|
HIPBLASLT_MATMUL_DESC_A_SCALE_MODE,
|
|
&scale_mode_a_r,
|
|
sizeof(uint32_t),
|
|
&sizeWritten),
|
|
HIPBLAS_STATUS_SUCCESS);
|
|
|
|
ASSERT_TRUE(scale_mode_a_r == scale_mode_a); // validate
|
|
|
|
// HIPBLASLT_MATMUL_DESC_B_SCALE_MODE
|
|
|
|
hipblasLtMatmulMatrixScale_t scale_mode_b = HIPBLASLT_MATMUL_MATRIX_SCALE_VEC32_UE8M0;
|
|
hipblasLtMatmulMatrixScale_t scale_mode_b_r = HIPBLASLT_MATMUL_MATRIX_SCALE_END;
|
|
|
|
EXPECT_HIPBLAS_STATUS(hipblasLtMatmulDescGetAttribute(matmul,
|
|
HIPBLASLT_MATMUL_DESC_B_SCALE_MODE,
|
|
&scale_mode_b_r,
|
|
sizeof(uint32_t),
|
|
&sizeWritten),
|
|
HIPBLAS_STATUS_INVALID_VALUE); // we didn't set it yet, so we get error
|
|
|
|
EXPECT_HIPBLAS_STATUS(
|
|
hipblasLtMatmulDescSetAttribute(
|
|
matmul, HIPBLASLT_MATMUL_DESC_B_SCALE_MODE, &scale_mode_b, sizeof(uint32_t) / 2),
|
|
HIPBLAS_STATUS_INVALID_VALUE);
|
|
|
|
EXPECT_HIPBLAS_STATUS(
|
|
hipblasLtMatmulDescSetAttribute(
|
|
matmul, HIPBLASLT_MATMUL_DESC_B_SCALE_MODE, &scale_mode_b, sizeof(uint32_t)),
|
|
HIPBLAS_STATUS_SUCCESS);
|
|
|
|
EXPECT_HIPBLAS_STATUS(hipblasLtMatmulDescGetAttribute(matmul,
|
|
HIPBLASLT_MATMUL_DESC_B_SCALE_MODE,
|
|
&scale_mode_b_r,
|
|
sizeof(uint32_t) / 2,
|
|
&sizeWritten),
|
|
HIPBLAS_STATUS_INVALID_VALUE);
|
|
|
|
EXPECT_HIPBLAS_STATUS(hipblasLtMatmulDescGetAttribute(matmul,
|
|
HIPBLASLT_MATMUL_DESC_B_SCALE_MODE,
|
|
&scale_mode_b_r,
|
|
sizeof(uint32_t),
|
|
&sizeWritten),
|
|
HIPBLAS_STATUS_SUCCESS);
|
|
|
|
ASSERT_TRUE(scale_mode_b_r == scale_mode_b); // validate
|
|
|
|
scale_mode_a = HIPBLASLT_MATMUL_MATRIX_SCALE_SCALAR_32F;
|
|
scale_mode_b = HIPBLASLT_MATMUL_MATRIX_SCALE_SCALAR_32F;
|
|
|
|
EXPECT_HIPBLAS_STATUS(
|
|
hipblasLtMatmulDescSetAttribute(
|
|
matmul, HIPBLASLT_MATMUL_DESC_A_SCALE_MODE, &scale_mode_a, sizeof(uint32_t)),
|
|
HIPBLAS_STATUS_SUCCESS);
|
|
|
|
EXPECT_HIPBLAS_STATUS(hipblasLtMatmulDescGetAttribute(matmul,
|
|
HIPBLASLT_MATMUL_DESC_A_SCALE_MODE,
|
|
&scale_mode_a_r,
|
|
sizeof(uint32_t),
|
|
&sizeWritten),
|
|
HIPBLAS_STATUS_SUCCESS);
|
|
|
|
EXPECT_HIPBLAS_STATUS(
|
|
hipblasLtMatmulDescSetAttribute(
|
|
matmul, HIPBLASLT_MATMUL_DESC_B_SCALE_MODE, &scale_mode_b, sizeof(uint32_t)),
|
|
HIPBLAS_STATUS_SUCCESS);
|
|
|
|
EXPECT_HIPBLAS_STATUS(hipblasLtMatmulDescGetAttribute(matmul,
|
|
HIPBLASLT_MATMUL_DESC_B_SCALE_MODE,
|
|
&scale_mode_b_r,
|
|
sizeof(uint32_t),
|
|
&sizeWritten),
|
|
HIPBLAS_STATUS_SUCCESS);
|
|
|
|
ASSERT_TRUE(scale_mode_a_r == scale_mode_a); // validate
|
|
ASSERT_TRUE(scale_mode_b_r == scale_mode_b); // ditto
|
|
|
|
scale_mode_a = HIPBLASLT_MATMUL_MATRIX_SCALE_OUTER_VEC_32F;
|
|
scale_mode_b = HIPBLASLT_MATMUL_MATRIX_SCALE_OUTER_VEC_32F;
|
|
|
|
EXPECT_HIPBLAS_STATUS(
|
|
hipblasLtMatmulDescSetAttribute(
|
|
matmul, HIPBLASLT_MATMUL_DESC_A_SCALE_MODE, &scale_mode_a, sizeof(uint32_t)),
|
|
HIPBLAS_STATUS_SUCCESS);
|
|
|
|
EXPECT_HIPBLAS_STATUS(hipblasLtMatmulDescGetAttribute(matmul,
|
|
HIPBLASLT_MATMUL_DESC_A_SCALE_MODE,
|
|
&scale_mode_a_r,
|
|
sizeof(uint32_t),
|
|
&sizeWritten),
|
|
HIPBLAS_STATUS_SUCCESS);
|
|
|
|
EXPECT_HIPBLAS_STATUS(
|
|
hipblasLtMatmulDescSetAttribute(
|
|
matmul, HIPBLASLT_MATMUL_DESC_B_SCALE_MODE, &scale_mode_b, sizeof(uint32_t)),
|
|
HIPBLAS_STATUS_SUCCESS);
|
|
|
|
EXPECT_HIPBLAS_STATUS(hipblasLtMatmulDescGetAttribute(matmul,
|
|
HIPBLASLT_MATMUL_DESC_B_SCALE_MODE,
|
|
&scale_mode_b_r,
|
|
sizeof(uint32_t),
|
|
&sizeWritten),
|
|
HIPBLAS_STATUS_SUCCESS);
|
|
|
|
ASSERT_TRUE(scale_mode_a_r == scale_mode_a); // validate
|
|
|
|
scale_mode_a = HIPBLASLT_MATMUL_MATRIX_SCALE_VEC16_UE4M3;
|
|
scale_mode_b = HIPBLASLT_MATMUL_MATRIX_SCALE_VEC16_UE4M3;
|
|
|
|
EXPECT_HIPBLAS_STATUS(
|
|
hipblasLtMatmulDescSetAttribute(
|
|
matmul, HIPBLASLT_MATMUL_DESC_A_SCALE_MODE, &scale_mode_a, sizeof(uint32_t)),
|
|
HIPBLAS_STATUS_SUCCESS);
|
|
|
|
EXPECT_HIPBLAS_STATUS(hipblasLtMatmulDescGetAttribute(matmul,
|
|
HIPBLASLT_MATMUL_DESC_A_SCALE_MODE,
|
|
&scale_mode_a_r,
|
|
sizeof(uint32_t),
|
|
&sizeWritten),
|
|
HIPBLAS_STATUS_SUCCESS);
|
|
|
|
EXPECT_HIPBLAS_STATUS(
|
|
hipblasLtMatmulDescSetAttribute(
|
|
matmul, HIPBLASLT_MATMUL_DESC_B_SCALE_MODE, &scale_mode_b, sizeof(uint32_t)),
|
|
HIPBLAS_STATUS_SUCCESS);
|
|
|
|
EXPECT_HIPBLAS_STATUS(hipblasLtMatmulDescGetAttribute(matmul,
|
|
HIPBLASLT_MATMUL_DESC_B_SCALE_MODE,
|
|
&scale_mode_b_r,
|
|
sizeof(uint32_t),
|
|
&sizeWritten),
|
|
HIPBLAS_STATUS_SUCCESS);
|
|
|
|
ASSERT_TRUE(
|
|
scale_mode_a_r
|
|
== HIPBLASLT_MATMUL_MATRIX_SCALE_VEC16_UE4M3); // validate round-trip
|
|
ASSERT_TRUE(scale_mode_b_r == HIPBLASLT_MATMUL_MATRIX_SCALE_VEC16_UE4M3); // ditto
|
|
|
|
hipStream_t stream;
|
|
CHECK_HIP_ERROR(hipStreamCreate(&stream));
|
|
|
|
// for HIPBLASLT_MATMUL_DESC_B_SCALE_POINTER
|
|
float h_scale_b = 3.f;
|
|
float* d_scale_b;
|
|
float* d_scale_b_r;
|
|
CHECK_HIP_ERROR(hipMalloc(&d_scale_b, sizeof(float)));
|
|
CHECK_HIP_ERROR(
|
|
hipMemcpyAsync(d_scale_b, &h_scale_b, sizeof(float), hipMemcpyHostToDevice, stream));
|
|
|
|
EXPECT_HIPBLAS_STATUS(
|
|
hipblasLtMatmulDescSetAttribute(
|
|
matmul, HIPBLASLT_MATMUL_DESC_B_SCALE_POINTER, &d_scale_b, sizeof(float*) / 2),
|
|
HIPBLAS_STATUS_INVALID_VALUE);
|
|
|
|
EXPECT_HIPBLAS_STATUS(
|
|
hipblasLtMatmulDescSetAttribute(
|
|
matmul, HIPBLASLT_MATMUL_DESC_B_SCALE_POINTER, &d_scale_b, sizeof(float*)),
|
|
HIPBLAS_STATUS_SUCCESS);
|
|
|
|
EXPECT_HIPBLAS_STATUS(hipblasLtMatmulDescGetAttribute(matmul,
|
|
HIPBLASLT_MATMUL_DESC_B_SCALE_POINTER,
|
|
&d_scale_b_r,
|
|
sizeof(float*) / 2,
|
|
&sizeWritten),
|
|
HIPBLAS_STATUS_INVALID_VALUE);
|
|
|
|
EXPECT_HIPBLAS_STATUS(hipblasLtMatmulDescGetAttribute(matmul,
|
|
HIPBLASLT_MATMUL_DESC_B_SCALE_POINTER,
|
|
&d_scale_b_r,
|
|
sizeof(float*),
|
|
&sizeWritten),
|
|
HIPBLAS_STATUS_SUCCESS);
|
|
|
|
ASSERT_TRUE(d_scale_b == d_scale_b_r); // validate
|
|
|
|
// for HIPBLASLT_MATMUL_DESC_C_SCALE_POINTER & HIPBLASLT_MATMUL_DESC_D_SCALE_POINTER
|
|
float h_scale_c = 3.f;
|
|
float h_scale_d = 3.f;
|
|
float* d_scale_c;
|
|
float* d_scale_d;
|
|
CHECK_HIP_ERROR(hipMalloc(&d_scale_c, sizeof(float)));
|
|
CHECK_HIP_ERROR(hipMalloc(&d_scale_d, sizeof(float)));
|
|
CHECK_HIP_ERROR(
|
|
hipMemcpyAsync(d_scale_c, &h_scale_c, sizeof(float), hipMemcpyHostToDevice, stream));
|
|
CHECK_HIP_ERROR(
|
|
hipMemcpyAsync(d_scale_d, &h_scale_d, sizeof(float), hipMemcpyHostToDevice, stream));
|
|
|
|
EXPECT_HIPBLAS_STATUS(
|
|
hipblasLtMatmulDescSetAttribute(
|
|
matmul, HIPBLASLT_MATMUL_DESC_C_SCALE_POINTER, &d_scale_c, sizeof(float*) / 2),
|
|
HIPBLAS_STATUS_INVALID_VALUE);
|
|
|
|
EXPECT_HIPBLAS_STATUS(
|
|
hipblasLtMatmulDescSetAttribute(
|
|
matmul, HIPBLASLT_MATMUL_DESC_C_SCALE_POINTER, &d_scale_c, sizeof(float*)),
|
|
HIPBLAS_STATUS_SUCCESS);
|
|
|
|
EXPECT_HIPBLAS_STATUS(
|
|
hipblasLtMatmulDescSetAttribute(
|
|
matmul, HIPBLASLT_MATMUL_DESC_D_SCALE_POINTER, &d_scale_d, sizeof(float*) / 2),
|
|
HIPBLAS_STATUS_INVALID_VALUE);
|
|
|
|
EXPECT_HIPBLAS_STATUS(
|
|
hipblasLtMatmulDescSetAttribute(
|
|
matmul, HIPBLASLT_MATMUL_DESC_D_SCALE_POINTER, &d_scale_d, sizeof(float*)),
|
|
HIPBLAS_STATUS_SUCCESS);
|
|
|
|
// for HIPBLASLT_MATMUL_DESC_EPILOGUE_AUX_SCALE_POINTER
|
|
float h_scale_e = 3.f;
|
|
float* d_scale_e;
|
|
CHECK_HIP_ERROR(hipMalloc(&d_scale_e, sizeof(float)));
|
|
CHECK_HIP_ERROR(
|
|
hipMemcpyAsync(d_scale_e, &h_scale_e, sizeof(float), hipMemcpyHostToDevice, stream));
|
|
|
|
EXPECT_HIPBLAS_STATUS(
|
|
hipblasLtMatmulDescSetAttribute(matmul,
|
|
HIPBLASLT_MATMUL_DESC_EPILOGUE_AUX_SCALE_POINTER,
|
|
&d_scale_e,
|
|
sizeof(float*) / 2),
|
|
HIPBLAS_STATUS_INVALID_VALUE);
|
|
|
|
EXPECT_HIPBLAS_STATUS(
|
|
hipblasLtMatmulDescSetAttribute(
|
|
matmul, HIPBLASLT_MATMUL_DESC_EPILOGUE_AUX_SCALE_POINTER, &d_scale_e, sizeof(float*)),
|
|
HIPBLAS_STATUS_SUCCESS);
|
|
|
|
// For HIPBLASLT_MATMUL_DESC_POINTER_MODE
|
|
hipblasLtPointerMode_t pMode = HIPBLASLT_POINTER_MODE_ALPHA_DEVICE_VECTOR_BETA_HOST;
|
|
hipblasLtPointerMode_t pMode_r = HIPBLASLT_POINTER_MODE_HOST;
|
|
EXPECT_HIPBLAS_STATUS(
|
|
hipblasLtMatmulDescSetAttribute(
|
|
matmul, HIPBLASLT_MATMUL_DESC_POINTER_MODE, &pMode, sizeof(pMode) / 2),
|
|
HIPBLAS_STATUS_INVALID_VALUE);
|
|
EXPECT_HIPBLAS_STATUS(hipblasLtMatmulDescSetAttribute(
|
|
matmul, HIPBLASLT_MATMUL_DESC_POINTER_MODE, &pMode, sizeof(pMode)),
|
|
HIPBLAS_STATUS_SUCCESS);
|
|
EXPECT_HIPBLAS_STATUS(hipblasLtMatmulDescGetAttribute(matmul,
|
|
HIPBLASLT_MATMUL_DESC_POINTER_MODE,
|
|
&pMode_r,
|
|
sizeof(pMode_r) / 2,
|
|
&sizeWritten),
|
|
HIPBLAS_STATUS_INVALID_VALUE);
|
|
EXPECT_HIPBLAS_STATUS(
|
|
hipblasLtMatmulDescGetAttribute(
|
|
matmul, HIPBLASLT_MATMUL_DESC_POINTER_MODE, &pMode_r, sizeof(pMode_r), &sizeWritten),
|
|
HIPBLAS_STATUS_SUCCESS);
|
|
|
|
ASSERT_TRUE(pMode_r == pMode); // validate
|
|
|
|
// For HIPBLASLT_MATMUL_DESC_BIAS_DATA_TYPE Set Desc Bias Data Type
|
|
int32_t bias_data_type = HIP_R_16F;
|
|
int32_t bias_data_type_r = HIP_R_32F;
|
|
|
|
EXPECT_HIPBLAS_STATUS(hipblasLtMatmulDescSetAttribute(matmul,
|
|
HIPBLASLT_MATMUL_DESC_BIAS_DATA_TYPE,
|
|
&bias_data_type,
|
|
sizeof(bias_data_type) / 2),
|
|
HIPBLAS_STATUS_INVALID_VALUE);
|
|
|
|
EXPECT_HIPBLAS_STATUS(
|
|
hipblasLtMatmulDescSetAttribute(
|
|
matmul, HIPBLASLT_MATMUL_DESC_BIAS_DATA_TYPE, &bias_data_type, sizeof(bias_data_type)),
|
|
HIPBLAS_STATUS_SUCCESS);
|
|
|
|
EXPECT_HIPBLAS_STATUS(hipblasLtMatmulDescGetAttribute(matmul,
|
|
HIPBLASLT_MATMUL_DESC_BIAS_DATA_TYPE,
|
|
&bias_data_type_r,
|
|
sizeof(bias_data_type_r) / 2,
|
|
&sizeWritten),
|
|
HIPBLAS_STATUS_INVALID_VALUE);
|
|
|
|
EXPECT_HIPBLAS_STATUS(hipblasLtMatmulDescGetAttribute(matmul,
|
|
HIPBLASLT_MATMUL_DESC_BIAS_DATA_TYPE,
|
|
&bias_data_type_r,
|
|
sizeof(bias_data_type_r),
|
|
&sizeWritten),
|
|
HIPBLAS_STATUS_SUCCESS);
|
|
|
|
ASSERT_TRUE(bias_data_type_r == bias_data_type); // validate
|
|
|
|
// For HIPBLASLT_MATMUL_DESC_EPILOGUE_AUX_POINTER Set auxiliary buffer
|
|
void* d_aux_buffer;
|
|
CHECK_HIP_ERROR(hipMalloc(&d_aux_buffer, m * n * sizeof(hipblasLtHalf)));
|
|
EXPECT_HIPBLAS_STATUS(
|
|
hipblasLtMatmulDescSetAttribute(
|
|
matmul, HIPBLASLT_MATMUL_DESC_EPILOGUE_AUX_POINTER, &d_aux_buffer, sizeof(void*) / 2),
|
|
HIPBLAS_STATUS_INVALID_VALUE);
|
|
EXPECT_HIPBLAS_STATUS(
|
|
hipblasLtMatmulDescSetAttribute(
|
|
matmul, HIPBLASLT_MATMUL_DESC_EPILOGUE_AUX_POINTER, &d_aux_buffer, sizeof(void*)),
|
|
HIPBLAS_STATUS_SUCCESS);
|
|
|
|
// For HIPBLASLT_MATMUL_DESC_EPILOGUE_AUX_LD Set auxiliary leading dimension (ld)
|
|
const int64_t aux_ld = m;
|
|
EXPECT_HIPBLAS_STATUS(
|
|
hipblasLtMatmulDescSetAttribute(
|
|
matmul, HIPBLASLT_MATMUL_DESC_EPILOGUE_AUX_LD, &aux_ld, sizeof(aux_ld) / 2),
|
|
HIPBLAS_STATUS_INVALID_VALUE);
|
|
|
|
EXPECT_HIPBLAS_STATUS(
|
|
hipblasLtMatmulDescSetAttribute(
|
|
matmul, HIPBLASLT_MATMUL_DESC_EPILOGUE_AUX_LD, &aux_ld, sizeof(aux_ld)),
|
|
HIPBLAS_STATUS_SUCCESS);
|
|
|
|
// for HIPBLASLT_MATMUL_DESC_EPILOGUE_AUX_BATCH_STRIDE & Set Epilogue Aux Batch Stride
|
|
const int64_t aux_batch_stride = m * n;
|
|
EXPECT_HIPBLAS_STATUS(
|
|
hipblasLtMatmulDescSetAttribute(matmul,
|
|
HIPBLASLT_MATMUL_DESC_EPILOGUE_AUX_BATCH_STRIDE,
|
|
&aux_batch_stride,
|
|
sizeof(aux_batch_stride) / 2),
|
|
HIPBLAS_STATUS_INVALID_VALUE);
|
|
|
|
EXPECT_HIPBLAS_STATUS(
|
|
hipblasLtMatmulDescSetAttribute(matmul,
|
|
HIPBLASLT_MATMUL_DESC_EPILOGUE_AUX_BATCH_STRIDE,
|
|
&aux_batch_stride,
|
|
sizeof(aux_batch_stride)),
|
|
HIPBLAS_STATUS_SUCCESS);
|
|
|
|
// for HIPBLASLT_MATMUL_DESC_AMAX_D_POINTER
|
|
void* d_out_amax;
|
|
void* d_out_amax_r;
|
|
CHECK_HIP_ERROR(hipMalloc(&d_out_amax, 1 * sizeof(float)));
|
|
EXPECT_HIPBLAS_STATUS(
|
|
hipblasLtMatmulDescSetAttribute(
|
|
matmul, HIPBLASLT_MATMUL_DESC_AMAX_D_POINTER, &d_out_amax, sizeof(void*) / 2),
|
|
HIPBLAS_STATUS_INVALID_VALUE);
|
|
|
|
EXPECT_HIPBLAS_STATUS(
|
|
hipblasLtMatmulDescSetAttribute(
|
|
matmul, HIPBLASLT_MATMUL_DESC_AMAX_D_POINTER, &d_out_amax, sizeof(void*)),
|
|
HIPBLAS_STATUS_SUCCESS);
|
|
|
|
EXPECT_HIPBLAS_STATUS(hipblasLtMatmulDescGetAttribute(matmul,
|
|
HIPBLASLT_MATMUL_DESC_AMAX_D_POINTER,
|
|
&d_out_amax_r,
|
|
sizeof(d_out_amax_r) / 2,
|
|
&sizeWritten),
|
|
HIPBLAS_STATUS_INVALID_VALUE);
|
|
|
|
EXPECT_HIPBLAS_STATUS(hipblasLtMatmulDescGetAttribute(matmul,
|
|
HIPBLASLT_MATMUL_DESC_AMAX_D_POINTER,
|
|
&d_out_amax_r,
|
|
sizeof(d_out_amax_r),
|
|
&sizeWritten),
|
|
HIPBLAS_STATUS_SUCCESS);
|
|
|
|
ASSERT_TRUE(d_out_amax == d_out_amax_r); // validate
|
|
|
|
// for HIPBLASLT_MATMUL_DESC_EPILOGUE_AUX_DATA_TYPE
|
|
hipDataType aux_type_r;
|
|
EXPECT_HIPBLAS_STATUS(
|
|
hipblasLtMatmulDescSetAttribute(matmul,
|
|
HIPBLASLT_MATMUL_DESC_EPILOGUE_AUX_DATA_TYPE,
|
|
&arg.aux_type,
|
|
sizeof(hipDataType) / 2),
|
|
HIPBLAS_STATUS_INVALID_VALUE);
|
|
|
|
EXPECT_HIPBLAS_STATUS(
|
|
hipblasLtMatmulDescSetAttribute(matmul,
|
|
HIPBLASLT_MATMUL_DESC_EPILOGUE_AUX_DATA_TYPE,
|
|
&arg.aux_type,
|
|
sizeof(hipDataType)),
|
|
HIPBLAS_STATUS_SUCCESS);
|
|
|
|
EXPECT_HIPBLAS_STATUS(
|
|
hipblasLtMatmulDescGetAttribute(matmul,
|
|
HIPBLASLT_MATMUL_DESC_EPILOGUE_AUX_DATA_TYPE,
|
|
&aux_type_r,
|
|
sizeof(aux_type_r) / 2,
|
|
&sizeWritten),
|
|
HIPBLAS_STATUS_INVALID_VALUE);
|
|
|
|
EXPECT_HIPBLAS_STATUS(
|
|
hipblasLtMatmulDescGetAttribute(matmul,
|
|
HIPBLASLT_MATMUL_DESC_EPILOGUE_AUX_DATA_TYPE,
|
|
&aux_type_r,
|
|
sizeof(aux_type_r),
|
|
&sizeWritten),
|
|
HIPBLAS_STATUS_SUCCESS);
|
|
|
|
ASSERT_TRUE(arg.aux_type == aux_type_r); // validate
|
|
|
|
// for HIPBLASLT_MATMUL_DESC_COMPUTE_INPUT_TYPE_A_EXT & HIPBLASLT_MATMUL_DESC_COMPUTE_INPUT_TYPE_B_EXT
|
|
hipDataType computeTypeA = HIP_R_16F;
|
|
hipDataType computeTypeA_r = HIP_R_32F;
|
|
hipDataType computeTypeB = HIP_R_16F;
|
|
hipDataType computeTypeB_r = HIP_R_32F;
|
|
|
|
EXPECT_HIPBLAS_STATUS(
|
|
hipblasLtMatmulDescSetAttribute(matmul,
|
|
HIPBLASLT_MATMUL_DESC_COMPUTE_INPUT_TYPE_A_EXT,
|
|
&computeTypeA,
|
|
sizeof(computeTypeA) / 2),
|
|
HIPBLAS_STATUS_INVALID_VALUE);
|
|
|
|
EXPECT_HIPBLAS_STATUS(
|
|
hipblasLtMatmulDescSetAttribute(matmul,
|
|
HIPBLASLT_MATMUL_DESC_COMPUTE_INPUT_TYPE_A_EXT,
|
|
&computeTypeA,
|
|
sizeof(computeTypeA)),
|
|
HIPBLAS_STATUS_SUCCESS);
|
|
|
|
EXPECT_HIPBLAS_STATUS(
|
|
hipblasLtMatmulDescSetAttribute(matmul,
|
|
HIPBLASLT_MATMUL_DESC_COMPUTE_INPUT_TYPE_B_EXT,
|
|
&computeTypeB,
|
|
sizeof(computeTypeB) / 2),
|
|
HIPBLAS_STATUS_INVALID_VALUE);
|
|
|
|
EXPECT_HIPBLAS_STATUS(
|
|
hipblasLtMatmulDescSetAttribute(matmul,
|
|
HIPBLASLT_MATMUL_DESC_COMPUTE_INPUT_TYPE_B_EXT,
|
|
&computeTypeB,
|
|
sizeof(computeTypeB)),
|
|
HIPBLAS_STATUS_SUCCESS);
|
|
|
|
EXPECT_HIPBLAS_STATUS(
|
|
hipblasLtMatmulDescGetAttribute(matmul,
|
|
HIPBLASLT_MATMUL_DESC_COMPUTE_INPUT_TYPE_A_EXT,
|
|
&computeTypeA_r,
|
|
sizeof(computeTypeA_r) / 2,
|
|
&sizeWritten),
|
|
HIPBLAS_STATUS_INVALID_VALUE);
|
|
|
|
EXPECT_HIPBLAS_STATUS(
|
|
hipblasLtMatmulDescGetAttribute(matmul,
|
|
HIPBLASLT_MATMUL_DESC_COMPUTE_INPUT_TYPE_A_EXT,
|
|
&computeTypeA_r,
|
|
sizeof(computeTypeA_r),
|
|
&sizeWritten),
|
|
HIPBLAS_STATUS_SUCCESS);
|
|
|
|
EXPECT_HIPBLAS_STATUS(
|
|
hipblasLtMatmulDescGetAttribute(matmul,
|
|
HIPBLASLT_MATMUL_DESC_COMPUTE_INPUT_TYPE_B_EXT,
|
|
&computeTypeB_r,
|
|
sizeof(computeTypeB_r) / 2,
|
|
&sizeWritten),
|
|
HIPBLAS_STATUS_INVALID_VALUE);
|
|
|
|
EXPECT_HIPBLAS_STATUS(
|
|
hipblasLtMatmulDescGetAttribute(matmul,
|
|
HIPBLASLT_MATMUL_DESC_COMPUTE_INPUT_TYPE_B_EXT,
|
|
&computeTypeB_r,
|
|
sizeof(computeTypeB_r),
|
|
&sizeWritten),
|
|
HIPBLAS_STATUS_SUCCESS);
|
|
|
|
ASSERT_TRUE(computeTypeA_r == computeTypeA);
|
|
ASSERT_TRUE(computeTypeB_r == computeTypeB);
|
|
|
|
// for default
|
|
|
|
void* default_ptr;
|
|
void* default_ptr_r;
|
|
CHECK_HIP_ERROR(hipMalloc(&default_ptr, sizeof(hipblasLtHalf)));
|
|
EXPECT_HIPBLAS_STATUS(hipblasLtMatmulDescSetAttribute(
|
|
matmul, HIPBLASLT_MATMUL_DESC_MAX, &default_ptr, sizeof(void*)),
|
|
HIPBLAS_STATUS_INVALID_VALUE);
|
|
|
|
EXPECT_HIPBLAS_STATUS(
|
|
hipblasLtMatmulDescGetAttribute(
|
|
matmul, HIPBLASLT_MATMUL_DESC_MAX, &default_ptr_r, sizeof(default_ptr_r), &sizeWritten),
|
|
HIPBLAS_STATUS_INVALID_VALUE);
|
|
|
|
CHECK_HIPBLASLT_ERROR(hipblasLtMatmulDescDestroy(matmul));
|
|
CHECK_HIP_ERROR(hipStreamDestroy(stream));
|
|
CHECK_HIP_ERROR(hipFree(d_scale_a));
|
|
CHECK_HIP_ERROR(hipFree(d_bias));
|
|
CHECK_HIP_ERROR(hipFree(d_scale_b));
|
|
CHECK_HIP_ERROR(hipFree(d_scale_c));
|
|
CHECK_HIP_ERROR(hipFree(d_scale_d));
|
|
CHECK_HIP_ERROR(hipFree(d_scale_e));
|
|
CHECK_HIP_ERROR(hipFree(d_aux_buffer));
|
|
CHECK_HIP_ERROR(hipFree(d_out_amax));
|
|
CHECK_HIP_ERROR(hipFree(default_ptr));
|
|
}
|
|
|
|
void testing_aux_matmul_pref_get_attr_bad_arg(const Arguments& arg)
|
|
{
|
|
hipblaslt_local_preference pref;
|
|
EXPECT_HIPBLAS_STATUS(pref.status(), HIPBLAS_STATUS_SUCCESS);
|
|
|
|
uint64_t data;
|
|
size_t sizeWritten;
|
|
|
|
// Test with null preference (should be INVALID_VALUE)
|
|
EXPECT_HIPBLAS_STATUS(
|
|
hipblasLtMatmulPreferenceGetAttribute(
|
|
nullptr, HIPBLASLT_MATMUL_PREF_MAX_WORKSPACE_BYTES, &data, sizeof(data), &sizeWritten),
|
|
HIPBLAS_STATUS_INVALID_VALUE);
|
|
|
|
// Test with sizeInBytes = 0 and sizeWritten = NULL (should be INVALID_VALUE)
|
|
EXPECT_HIPBLAS_STATUS(hipblasLtMatmulPreferenceGetAttribute(
|
|
pref, HIPBLASLT_MATMUL_PREF_MAX_WORKSPACE_BYTES, &data, 0, nullptr),
|
|
HIPBLAS_STATUS_INVALID_VALUE);
|
|
|
|
// Test with non-zero sizeInBytes and buf = NULL (should be INVALID_VALUE)
|
|
EXPECT_HIPBLAS_STATUS(
|
|
hipblasLtMatmulPreferenceGetAttribute(pref,
|
|
HIPBLASLT_MATMUL_PREF_MAX_WORKSPACE_BYTES,
|
|
nullptr,
|
|
sizeof(uint64_t),
|
|
&sizeWritten),
|
|
HIPBLAS_STATUS_INVALID_VALUE);
|
|
|
|
// Test with correct size (should be SUCCESS)
|
|
EXPECT_HIPBLAS_STATUS(
|
|
hipblasLtMatmulPreferenceGetAttribute(
|
|
pref, HIPBLASLT_MATMUL_PREF_MAX_WORKSPACE_BYTES, &data, sizeof(uint64_t), &sizeWritten),
|
|
HIPBLAS_STATUS_SUCCESS);
|
|
}
|
|
|
|
void testing_aux_matmul_pref_get_attr(const Arguments& arg)
|
|
{
|
|
hipblaslt_local_preference pref;
|
|
EXPECT_HIPBLAS_STATUS(pref.status(), HIPBLAS_STATUS_SUCCESS);
|
|
|
|
uint64_t data_set = 1024;
|
|
uint64_t data_get = 0;
|
|
size_t sizeWritten;
|
|
|
|
// Test edge cases
|
|
EXPECT_HIPBLAS_STATUS(
|
|
hipblasLtMatmulPreferenceSetAttribute(
|
|
nullptr, HIPBLASLT_MATMUL_PREF_MAX_WORKSPACE_BYTES, &data_set, sizeof(data_set)),
|
|
HIPBLAS_STATUS_INVALID_VALUE);
|
|
|
|
EXPECT_HIPBLAS_STATUS(hipblasLtMatmulPreferenceSetAttribute(
|
|
pref, HIPBLASLT_MATMUL_PREF_MAX_WORKSPACE_BYTES, &data_set, 0),
|
|
HIPBLAS_STATUS_INVALID_VALUE);
|
|
|
|
EXPECT_HIPBLAS_STATUS(
|
|
hipblasLtMatmulPreferenceGetAttribute(
|
|
pref, HIPBLASLT_MATMUL_PREF_MAX_WORKSPACE_BYTES, nullptr, 0, &sizeWritten),
|
|
HIPBLAS_STATUS_INVALID_VALUE);
|
|
// Set the attribute
|
|
EXPECT_HIPBLAS_STATUS(
|
|
hipblasLtMatmulPreferenceSetAttribute(
|
|
pref, HIPBLASLT_MATMUL_PREF_MAX_WORKSPACE_BYTES, &data_set, sizeof(data_set)),
|
|
HIPBLAS_STATUS_SUCCESS);
|
|
|
|
// Get the attribute
|
|
EXPECT_HIPBLAS_STATUS(
|
|
hipblasLtMatmulPreferenceGetAttribute(pref,
|
|
HIPBLASLT_MATMUL_PREF_MAX_WORKSPACE_BYTES,
|
|
&data_get,
|
|
sizeof(data_get),
|
|
&sizeWritten),
|
|
HIPBLAS_STATUS_SUCCESS);
|
|
|
|
// Verify that the get value matches the set value
|
|
ASSERT_TRUE(data_get == data_set);
|
|
ASSERT_TRUE(sizeWritten == sizeof(data_get));
|
|
|
|
// Test getting other attributes (assuming they have default values)
|
|
int32_t search_mode = 0;
|
|
int32_t search_mode_r = 1;
|
|
EXPECT_HIPBLAS_STATUS(
|
|
hipblasLtMatmulPreferenceSetAttribute(
|
|
pref, HIPBLASLT_MATMUL_PREF_SEARCH_MODE, &search_mode, sizeof(search_mode)),
|
|
HIPBLAS_STATUS_SUCCESS);
|
|
|
|
EXPECT_HIPBLAS_STATUS(hipblasLtMatmulPreferenceGetAttribute(pref,
|
|
HIPBLASLT_MATMUL_PREF_SEARCH_MODE,
|
|
&search_mode_r,
|
|
sizeof(search_mode_r),
|
|
&sizeWritten),
|
|
HIPBLAS_STATUS_SUCCESS);
|
|
ASSERT_TRUE(data_get == data_set);
|
|
|
|
// Test default value
|
|
EXPECT_HIPBLAS_STATUS(hipblasLtMatmulPreferenceSetAttribute(
|
|
pref, HIPBLASLT_MATMUL_PREF_MAX, &search_mode, sizeof(search_mode)),
|
|
HIPBLAS_STATUS_INVALID_VALUE);
|
|
|
|
EXPECT_HIPBLAS_STATUS(
|
|
hipblasLtMatmulPreferenceGetAttribute(
|
|
pref, HIPBLASLT_MATMUL_PREF_MAX, &search_mode_r, sizeof(search_mode_r), &sizeWritten),
|
|
HIPBLAS_STATUS_INVALID_VALUE);
|
|
|
|
// You might want to add more attribute tests here
|
|
}
|
|
|
|
void testing_aux_matmul_sm_count_target(const Arguments& arg)
|
|
{
|
|
size_t sizeWritten = 0;
|
|
hipblasLtMatmulDesc_t matmul = nullptr;
|
|
CHECK_HIPBLASLT_ERROR(hipblasLtMatmulDescCreate(&matmul, arg.compute_type, arg.scale_type));
|
|
|
|
// Default value must be 0 ("use all CUs the device exposes").
|
|
int32_t value_r = -1;
|
|
EXPECT_HIPBLAS_STATUS(hipblasLtMatmulDescGetAttribute(matmul,
|
|
HIPBLASLT_MATMUL_DESC_SM_COUNT_TARGET,
|
|
&value_r,
|
|
sizeof(value_r),
|
|
&sizeWritten),
|
|
HIPBLAS_STATUS_SUCCESS);
|
|
ASSERT_TRUE(value_r == 0);
|
|
ASSERT_TRUE(sizeWritten == sizeof(int32_t));
|
|
|
|
// Round-trip set/get with a valid value.
|
|
int32_t value_set = 80;
|
|
EXPECT_HIPBLAS_STATUS(hipblasLtMatmulDescSetAttribute(matmul,
|
|
HIPBLASLT_MATMUL_DESC_SM_COUNT_TARGET,
|
|
&value_set,
|
|
sizeof(value_set)),
|
|
HIPBLAS_STATUS_SUCCESS);
|
|
value_r = 0;
|
|
EXPECT_HIPBLAS_STATUS(hipblasLtMatmulDescGetAttribute(matmul,
|
|
HIPBLASLT_MATMUL_DESC_SM_COUNT_TARGET,
|
|
&value_r,
|
|
sizeof(value_r),
|
|
&sizeWritten),
|
|
HIPBLAS_STATUS_SUCCESS);
|
|
ASSERT_TRUE(value_r == value_set);
|
|
|
|
// Setting back to 0 (the "use all CUs" sentinel) must be accepted.
|
|
int32_t zero = 0;
|
|
EXPECT_HIPBLAS_STATUS(hipblasLtMatmulDescSetAttribute(
|
|
matmul, HIPBLASLT_MATMUL_DESC_SM_COUNT_TARGET, &zero, sizeof(zero)),
|
|
HIPBLAS_STATUS_SUCCESS);
|
|
|
|
// Negative values must be rejected and must leave the stored value unchanged.
|
|
int32_t negative = -5;
|
|
EXPECT_HIPBLAS_STATUS(hipblasLtMatmulDescSetAttribute(matmul,
|
|
HIPBLASLT_MATMUL_DESC_SM_COUNT_TARGET,
|
|
&negative,
|
|
sizeof(negative)),
|
|
HIPBLAS_STATUS_INVALID_VALUE);
|
|
value_r = -1;
|
|
EXPECT_HIPBLAS_STATUS(hipblasLtMatmulDescGetAttribute(matmul,
|
|
HIPBLASLT_MATMUL_DESC_SM_COUNT_TARGET,
|
|
&value_r,
|
|
sizeof(value_r),
|
|
&sizeWritten),
|
|
HIPBLAS_STATUS_SUCCESS);
|
|
ASSERT_TRUE(value_r == 0); // unchanged (last successful set was 0)
|
|
|
|
// Undersized buffer is INVALID_VALUE for both set and get.
|
|
EXPECT_HIPBLAS_STATUS(hipblasLtMatmulDescSetAttribute(matmul,
|
|
HIPBLASLT_MATMUL_DESC_SM_COUNT_TARGET,
|
|
&value_set,
|
|
sizeof(int32_t) / 2),
|
|
HIPBLAS_STATUS_INVALID_VALUE);
|
|
EXPECT_HIPBLAS_STATUS(hipblasLtMatmulDescGetAttribute(matmul,
|
|
HIPBLASLT_MATMUL_DESC_SM_COUNT_TARGET,
|
|
&value_r,
|
|
sizeof(int32_t) / 2,
|
|
&sizeWritten),
|
|
HIPBLAS_STATUS_INVALID_VALUE);
|
|
|
|
CHECK_HIPBLASLT_ERROR(hipblasLtMatmulDescDestroy(matmul));
|
|
}
|
|
|
|
void testing_aux_matmul_streamk_tile_scheduling_ext(const Arguments& arg)
|
|
{
|
|
size_t sizeWritten = 0;
|
|
hipblasLtMatmulDesc_t matmul = nullptr;
|
|
CHECK_HIPBLASLT_ERROR(hipblasLtMatmulDescCreate(&matmul, arg.compute_type, arg.scale_type));
|
|
|
|
// Default is OFF (0); set sm_count_target > 0 to engage the heuristic.
|
|
int32_t value_r = -1;
|
|
EXPECT_HIPBLAS_STATUS(hipblasLtMatmulDescGetAttribute(matmul,
|
|
HIPBLASLT_MATMUL_DESC_STREAMK_TILE_SCHEDULING_EXT,
|
|
&value_r,
|
|
sizeof(value_r),
|
|
&sizeWritten),
|
|
HIPBLAS_STATUS_SUCCESS);
|
|
ASSERT_TRUE(value_r == 0);
|
|
|
|
// ON then OFF round-trip.
|
|
int32_t enable = 1;
|
|
EXPECT_HIPBLAS_STATUS(hipblasLtMatmulDescSetAttribute(matmul,
|
|
HIPBLASLT_MATMUL_DESC_STREAMK_TILE_SCHEDULING_EXT,
|
|
&enable,
|
|
sizeof(enable)),
|
|
HIPBLAS_STATUS_SUCCESS);
|
|
EXPECT_HIPBLAS_STATUS(hipblasLtMatmulDescGetAttribute(matmul,
|
|
HIPBLASLT_MATMUL_DESC_STREAMK_TILE_SCHEDULING_EXT,
|
|
&value_r,
|
|
sizeof(value_r),
|
|
&sizeWritten),
|
|
HIPBLAS_STATUS_SUCCESS);
|
|
ASSERT_TRUE(value_r == 1);
|
|
|
|
// AUTO (2) is also accepted and round-trips.
|
|
int32_t auto_mode = 2;
|
|
EXPECT_HIPBLAS_STATUS(hipblasLtMatmulDescSetAttribute(matmul,
|
|
HIPBLASLT_MATMUL_DESC_STREAMK_TILE_SCHEDULING_EXT,
|
|
&auto_mode,
|
|
sizeof(auto_mode)),
|
|
HIPBLAS_STATUS_SUCCESS);
|
|
EXPECT_HIPBLAS_STATUS(hipblasLtMatmulDescGetAttribute(matmul,
|
|
HIPBLASLT_MATMUL_DESC_STREAMK_TILE_SCHEDULING_EXT,
|
|
&value_r,
|
|
sizeof(value_r),
|
|
&sizeWritten),
|
|
HIPBLAS_STATUS_SUCCESS);
|
|
ASSERT_TRUE(value_r == 2);
|
|
|
|
// Values outside {0,1,2} are rejected with INVALID_VALUE (previously
|
|
// any nonzero value was silently clamped to 1).
|
|
int32_t three = 3;
|
|
EXPECT_HIPBLAS_STATUS(hipblasLtMatmulDescSetAttribute(matmul,
|
|
HIPBLASLT_MATMUL_DESC_STREAMK_TILE_SCHEDULING_EXT,
|
|
&three,
|
|
sizeof(three)),
|
|
HIPBLAS_STATUS_INVALID_VALUE);
|
|
int32_t negative = -1;
|
|
EXPECT_HIPBLAS_STATUS(hipblasLtMatmulDescSetAttribute(matmul,
|
|
HIPBLASLT_MATMUL_DESC_STREAMK_TILE_SCHEDULING_EXT,
|
|
&negative,
|
|
sizeof(negative)),
|
|
HIPBLAS_STATUS_INVALID_VALUE);
|
|
|
|
int32_t disable = 0;
|
|
EXPECT_HIPBLAS_STATUS(hipblasLtMatmulDescSetAttribute(matmul,
|
|
HIPBLASLT_MATMUL_DESC_STREAMK_TILE_SCHEDULING_EXT,
|
|
&disable,
|
|
sizeof(disable)),
|
|
HIPBLAS_STATUS_SUCCESS);
|
|
EXPECT_HIPBLAS_STATUS(hipblasLtMatmulDescGetAttribute(matmul,
|
|
HIPBLASLT_MATMUL_DESC_STREAMK_TILE_SCHEDULING_EXT,
|
|
&value_r,
|
|
sizeof(value_r),
|
|
&sizeWritten),
|
|
HIPBLAS_STATUS_SUCCESS);
|
|
ASSERT_TRUE(value_r == 0);
|
|
|
|
CHECK_HIPBLASLT_ERROR(hipblasLtMatmulDescDestroy(matmul));
|
|
}
|
|
|
|
void testing_aux_matmul_pref_sm_count_target(const Arguments& arg)
|
|
{
|
|
hipblaslt_local_preference pref;
|
|
EXPECT_HIPBLAS_STATUS(pref.status(), HIPBLAS_STATUS_SUCCESS);
|
|
|
|
int32_t value_r = -1;
|
|
size_t sizeWritten = 0;
|
|
|
|
// Default value must be 0.
|
|
EXPECT_HIPBLAS_STATUS(hipblasLtMatmulPreferenceGetAttribute(pref,
|
|
HIPBLASLT_MATMUL_PREF_SM_COUNT_TARGET,
|
|
&value_r,
|
|
sizeof(value_r),
|
|
&sizeWritten),
|
|
HIPBLAS_STATUS_SUCCESS);
|
|
ASSERT_TRUE(value_r == 0);
|
|
ASSERT_TRUE(sizeWritten == sizeof(int32_t));
|
|
|
|
// Round-trip set/get.
|
|
int32_t value_set = 132;
|
|
EXPECT_HIPBLAS_STATUS(hipblasLtMatmulPreferenceSetAttribute(pref,
|
|
HIPBLASLT_MATMUL_PREF_SM_COUNT_TARGET,
|
|
&value_set,
|
|
sizeof(value_set)),
|
|
HIPBLAS_STATUS_SUCCESS);
|
|
value_r = 0;
|
|
EXPECT_HIPBLAS_STATUS(hipblasLtMatmulPreferenceGetAttribute(pref,
|
|
HIPBLASLT_MATMUL_PREF_SM_COUNT_TARGET,
|
|
&value_r,
|
|
sizeof(value_r),
|
|
&sizeWritten),
|
|
HIPBLAS_STATUS_SUCCESS);
|
|
ASSERT_TRUE(value_r == value_set);
|
|
|
|
// Negative values must be rejected.
|
|
int32_t negative = -42;
|
|
EXPECT_HIPBLAS_STATUS(hipblasLtMatmulPreferenceSetAttribute(pref,
|
|
HIPBLASLT_MATMUL_PREF_SM_COUNT_TARGET,
|
|
&negative,
|
|
sizeof(negative)),
|
|
HIPBLAS_STATUS_INVALID_VALUE);
|
|
|
|
// Undersized buffer is INVALID_VALUE for both setter and getter.
|
|
EXPECT_HIPBLAS_STATUS(hipblasLtMatmulPreferenceSetAttribute(pref,
|
|
HIPBLASLT_MATMUL_PREF_SM_COUNT_TARGET,
|
|
&value_set,
|
|
sizeof(int32_t) / 2),
|
|
HIPBLAS_STATUS_INVALID_VALUE);
|
|
EXPECT_HIPBLAS_STATUS(hipblasLtMatmulPreferenceGetAttribute(pref,
|
|
HIPBLASLT_MATMUL_PREF_SM_COUNT_TARGET,
|
|
&value_r,
|
|
sizeof(int32_t) / 2,
|
|
&sizeWritten),
|
|
HIPBLAS_STATUS_INVALID_VALUE);
|
|
}
|
|
|
|
void testing_aux_matmul_alg_init_bad_arg(const Arguments& arg) {}
|
|
|
|
void testing_aux_matmul_alg_init(const Arguments& arg) {}
|
|
|
|
void testing_aux_get_sol_with_null_biasaddr(const Arguments& arg)
|
|
{
|
|
using InTypeA = hipblasLtHalf;
|
|
using InTypeB = hipblasLtHalf;
|
|
using OutType = hipblasLtHalf;
|
|
using AlphaType = hipblasLtFloat;
|
|
using BetaType = hipblasLtFloat;
|
|
|
|
hipStream_t stream;
|
|
hipblasLtHandle_t handle;
|
|
hipblasOperation_t trans_a = HIPBLAS_OP_N;
|
|
hipblasOperation_t trans_b = HIPBLAS_OP_T;
|
|
int64_t m = arg.M[0];
|
|
int64_t n = arg.N[0];
|
|
int64_t k = arg.K[0];
|
|
int64_t batch_count = 1;
|
|
float alpha = arg.alpha;
|
|
float beta = arg.beta;
|
|
void* d_a;
|
|
void* d_b;
|
|
void* d_c;
|
|
void* d_d;
|
|
void* a;
|
|
void* b;
|
|
void* c;
|
|
void* d;
|
|
|
|
CHECK_HIP_ERROR(hipStreamCreate(&stream));
|
|
CHECK_HIPBLASLT_ERROR(hipblasLtCreate(&handle));
|
|
CHECK_HIP_ERROR(hipMalloc(&d_a, m * k * batch_count * sizeof(InTypeA)));
|
|
CHECK_HIP_ERROR(hipMalloc(&d_b, n * k * batch_count * sizeof(InTypeB)));
|
|
CHECK_HIP_ERROR(hipMalloc(&d_c, m * n * batch_count * sizeof(OutType)));
|
|
CHECK_HIP_ERROR(hipMalloc(&d_d, m * n * batch_count * sizeof(OutType)));
|
|
CHECK_HIP_ERROR(hipHostMalloc(&a, m * k * batch_count * sizeof(InTypeA)));
|
|
CHECK_HIP_ERROR(hipHostMalloc(&b, n * k * batch_count * sizeof(InTypeB)));
|
|
CHECK_HIP_ERROR(hipHostMalloc(&c, m * n * batch_count * sizeof(OutType)));
|
|
CHECK_HIP_ERROR(hipHostMalloc(&d, m * n * batch_count * sizeof(OutType)));
|
|
|
|
CHECK_HIP_ERROR(hipMemcpyAsync(
|
|
d_a, a, m * k * batch_count * sizeof(InTypeA), hipMemcpyHostToDevice, stream));
|
|
CHECK_HIP_ERROR(hipMemcpyAsync(
|
|
d_b, b, n * k * batch_count * sizeof(InTypeB), hipMemcpyHostToDevice, stream));
|
|
CHECK_HIP_ERROR(hipMemcpyAsync(
|
|
d_c, c, m * n * batch_count * sizeof(OutType), hipMemcpyHostToDevice, stream));
|
|
|
|
hipblasLtMatrixLayout_t matA, matB, matC, matD;
|
|
CHECK_HIPBLASLT_ERROR(hipblasLtMatrixLayoutCreate(&matA, arg.a_type, m, k, m));
|
|
CHECK_HIPBLASLT_ERROR(hipblasLtMatrixLayoutCreate(&matB, arg.a_type, k, n, k));
|
|
CHECK_HIPBLASLT_ERROR(hipblasLtMatrixLayoutCreate(&matC, arg.a_type, m, n, m));
|
|
CHECK_HIPBLASLT_ERROR(hipblasLtMatrixLayoutCreate(&matD, arg.a_type, m, n, m));
|
|
|
|
hipblasLtMatmulDesc_t matmul;
|
|
hipblasLtEpilogue_t epilogue = HIPBLASLT_EPILOGUE_BIAS;
|
|
CHECK_HIPBLASLT_ERROR(hipblasLtMatmulDescCreate(&matmul, arg.compute_type, arg.scale_type));
|
|
CHECK_HIPBLASLT_ERROR(hipblasLtMatmulDescSetAttribute(
|
|
matmul, HIPBLASLT_MATMUL_DESC_TRANSA, &trans_a, sizeof(int32_t)));
|
|
CHECK_HIPBLASLT_ERROR(hipblasLtMatmulDescSetAttribute(
|
|
matmul, HIPBLASLT_MATMUL_DESC_TRANSB, &trans_b, sizeof(int32_t)));
|
|
CHECK_HIPBLASLT_ERROR(hipblasLtMatmulDescSetAttribute(
|
|
matmul, HIPBLASLT_MATMUL_DESC_EPILOGUE, &epilogue, sizeof(epilogue)));
|
|
|
|
hipblasLtMatmulPreference_t pref;
|
|
CHECK_HIPBLASLT_ERROR(hipblasLtMatmulPreferenceCreate(&pref));
|
|
const int request_solutions = 1;
|
|
hipblasLtMatmulHeuristicResult_t heuristicResult[request_solutions];
|
|
int returnedAlgoCount = 0;
|
|
CHECK_HIPBLASLT_ERROR(hipblasLtMatmulAlgoGetHeuristic(handle,
|
|
matmul,
|
|
matA,
|
|
matB,
|
|
matC,
|
|
matD,
|
|
pref,
|
|
request_solutions,
|
|
heuristicResult,
|
|
&returnedAlgoCount));
|
|
|
|
CHECK_SOLUTION_FOUND(returnedAlgoCount);
|
|
|
|
CHECK_HIP_ERROR(hipFree(a));
|
|
CHECK_HIP_ERROR(hipFree(b));
|
|
CHECK_HIP_ERROR(hipFree(c));
|
|
CHECK_HIP_ERROR(hipFree(d));
|
|
CHECK_HIP_ERROR(hipFree(d_a));
|
|
CHECK_HIP_ERROR(hipFree(d_b));
|
|
CHECK_HIP_ERROR(hipFree(d_c));
|
|
CHECK_HIP_ERROR(hipFree(d_d));
|
|
CHECK_HIPBLASLT_ERROR(hipblasLtMatmulDescDestroy(matmul));
|
|
CHECK_HIPBLASLT_ERROR(hipblasLtMatrixLayoutDestroy(matA));
|
|
CHECK_HIPBLASLT_ERROR(hipblasLtMatrixLayoutDestroy(matB));
|
|
CHECK_HIPBLASLT_ERROR(hipblasLtMatrixLayoutDestroy(matC));
|
|
CHECK_HIPBLASLT_ERROR(hipblasLtMatrixLayoutDestroy(matD));
|
|
CHECK_HIPBLASLT_ERROR(hipblasLtMatmulPreferenceDestroy(pref));
|
|
CHECK_HIPBLASLT_ERROR(hipblasLtDestroy(handle));
|
|
CHECK_HIP_ERROR(hipStreamDestroy(stream));
|
|
}
|
|
|
|
// hipBLASLt API: For testing case of (alpha=0 && (A=NULL || B=NULL))
|
|
void testing_aux_get_sol_with_zero_alpha_null_a_b(const Arguments& arg)
|
|
{
|
|
using InTypeA = hipblasLtHalf;
|
|
using InTypeB = hipblasLtHalf;
|
|
using OutType = hipblasLtHalf;
|
|
using AlphaType = hipblasLtFloat;
|
|
using BetaType = hipblasLtFloat;
|
|
|
|
hipStream_t stream;
|
|
hipblasLtHandle_t handle;
|
|
hipblasOperation_t trans_a = HIPBLAS_OP_N;
|
|
hipblasOperation_t trans_b = HIPBLAS_OP_T;
|
|
int64_t m = arg.M[0];
|
|
int64_t n = arg.N[0];
|
|
int64_t k = arg.K[0];
|
|
int64_t batch_count = 1;
|
|
// Setting alpha = 0.
|
|
float alpha = 0;
|
|
float beta = arg.beta;
|
|
// Setting d_a, d_b as nullptr.
|
|
void* d_a = NULL;
|
|
void* d_b = NULL;
|
|
void* d_c;
|
|
void* d_d;
|
|
|
|
CHECK_HIP_ERROR(hipStreamCreate(&stream));
|
|
CHECK_HIPBLASLT_ERROR(hipblasLtCreate(&handle));
|
|
CHECK_HIP_ERROR(hipMalloc(&d_c, m * n * batch_count * sizeof(OutType)));
|
|
CHECK_HIP_ERROR(hipMalloc(&d_d, m * n * batch_count * sizeof(OutType)));
|
|
|
|
hipblasLtMatrixLayout_t matA, matB, matC, matD;
|
|
CHECK_HIPBLASLT_ERROR(hipblasLtMatrixLayoutCreate(&matA, arg.a_type, m, k, m));
|
|
CHECK_HIPBLASLT_ERROR(hipblasLtMatrixLayoutCreate(&matB, arg.a_type, k, n, k));
|
|
CHECK_HIPBLASLT_ERROR(hipblasLtMatrixLayoutCreate(&matC, arg.a_type, m, n, m));
|
|
CHECK_HIPBLASLT_ERROR(hipblasLtMatrixLayoutCreate(&matD, arg.a_type, m, n, m));
|
|
|
|
hipblasLtMatmulDesc_t matmul;
|
|
CHECK_HIPBLASLT_ERROR(hipblasLtMatmulDescCreate(&matmul, arg.compute_type, arg.scale_type));
|
|
CHECK_HIPBLASLT_ERROR(hipblasLtMatmulDescSetAttribute(
|
|
matmul, HIPBLASLT_MATMUL_DESC_TRANSA, &trans_a, sizeof(int32_t)));
|
|
CHECK_HIPBLASLT_ERROR(hipblasLtMatmulDescSetAttribute(
|
|
matmul, HIPBLASLT_MATMUL_DESC_TRANSB, &trans_b, sizeof(int32_t)));
|
|
|
|
hipblasLtEpilogue_t epilogue = HIPBLASLT_EPILOGUE_DEFAULT;
|
|
CHECK_HIPBLASLT_ERROR(hipblasLtMatmulDescSetAttribute(
|
|
matmul, HIPBLASLT_MATMUL_DESC_EPILOGUE, &epilogue, sizeof(epilogue)));
|
|
|
|
// Set User Preference attributes
|
|
hipblasLtMatmulPreference_t pref;
|
|
CHECK_HIPBLASLT_ERROR(hipblasLtMatmulPreferenceCreate(&pref));
|
|
|
|
const int request_solutions = 1;
|
|
hipblasLtMatmulHeuristicResult_t heuristicResult[request_solutions];
|
|
int returnedAlgoCount = 0;
|
|
CHECK_HIPBLASLT_ERROR(hipblasLtMatmulAlgoGetHeuristic(handle,
|
|
matmul,
|
|
matA,
|
|
matB,
|
|
matC,
|
|
matD,
|
|
pref,
|
|
request_solutions,
|
|
heuristicResult,
|
|
&returnedAlgoCount));
|
|
|
|
CHECK_SOLUTION_FOUND(returnedAlgoCount);
|
|
|
|
// Validation for solution running.
|
|
CHECK_HIPBLASLT_ERROR(hipblasLtMatmul(handle,
|
|
matmul,
|
|
&alpha,
|
|
d_a,
|
|
matA,
|
|
d_b,
|
|
matB,
|
|
&beta,
|
|
d_c,
|
|
matC,
|
|
d_d,
|
|
matD,
|
|
&heuristicResult[0].algo,
|
|
nullptr,
|
|
0,
|
|
stream));
|
|
|
|
CHECK_HIP_ERROR(hipFree(d_c));
|
|
CHECK_HIP_ERROR(hipFree(d_d));
|
|
CHECK_HIPBLASLT_ERROR(hipblasLtMatmulDescDestroy(matmul));
|
|
CHECK_HIPBLASLT_ERROR(hipblasLtMatrixLayoutDestroy(matA));
|
|
CHECK_HIPBLASLT_ERROR(hipblasLtMatrixLayoutDestroy(matB));
|
|
CHECK_HIPBLASLT_ERROR(hipblasLtMatrixLayoutDestroy(matC));
|
|
CHECK_HIPBLASLT_ERROR(hipblasLtMatrixLayoutDestroy(matD));
|
|
CHECK_HIPBLASLT_ERROR(hipblasLtMatmulPreferenceDestroy(pref));
|
|
CHECK_HIPBLASLT_ERROR(hipblasLtDestroy(handle));
|
|
CHECK_HIP_ERROR(hipStreamDestroy(stream));
|
|
}
|
|
|
|
// hipBLASLtExt API: For testing case of (alpha=0 && (A=NULL || B=NULL))
|
|
void testing_aux_get_sol_with_zero_alpha_null_a_b_ext(const Arguments& arg)
|
|
{
|
|
using InTypeA = hipblasLtHalf;
|
|
using InTypeB = hipblasLtHalf;
|
|
using OutType = hipblasLtHalf;
|
|
using AlphaType = hipblasLtFloat;
|
|
using BetaType = hipblasLtFloat;
|
|
|
|
hipStream_t stream;
|
|
hipblasLtHandle_t handle;
|
|
hipblasOperation_t trans_a = HIPBLAS_OP_N;
|
|
hipblasOperation_t trans_b = HIPBLAS_OP_T;
|
|
int64_t m = arg.M[0];
|
|
int64_t n = arg.N[0];
|
|
int64_t k = arg.K[0];
|
|
int64_t batch_count = 1;
|
|
// Setting alpha = 0.
|
|
float alpha = 0;
|
|
float beta = arg.beta;
|
|
// Setting d_a, d_b as nullptr.
|
|
void* d_a = NULL;
|
|
void* d_b = NULL;
|
|
void* d_c;
|
|
void* d_d;
|
|
|
|
CHECK_HIP_ERROR(hipStreamCreate(&stream));
|
|
CHECK_HIPBLASLT_ERROR(hipblasLtCreate(&handle));
|
|
CHECK_HIP_ERROR(hipMalloc(&d_c, m * n * batch_count * sizeof(OutType)));
|
|
CHECK_HIP_ERROR(hipMalloc(&d_d, m * n * batch_count * sizeof(OutType)));
|
|
|
|
hipblaslt_ext::GemmPreference gemmPref;
|
|
hipblaslt_ext::Gemm gemm(
|
|
handle, trans_a, trans_b, arg.a_type, arg.a_type, arg.a_type, arg.a_type, arg.compute_type);
|
|
|
|
hipblaslt_ext::GemmEpilogue
|
|
epilogue; // No action needed, default is HIPBLASLT_EPILOGUE_DEFAULT. (Gemm only)
|
|
hipblaslt_ext::GemmInputs inputs;
|
|
inputs.setA(d_a);
|
|
inputs.setB(d_b);
|
|
inputs.setC(d_c);
|
|
inputs.setD(d_d);
|
|
inputs.setAlpha(&alpha);
|
|
inputs.setBeta(&beta);
|
|
gemm.setProblem(m, n, k, batch_count, epilogue, inputs);
|
|
|
|
const int request_solutions = 1;
|
|
std::vector<hipblasLtMatmulHeuristicResult_t> heuristicResult;
|
|
CHECK_HIPBLASLT_ERROR(gemm.algoGetHeuristic(request_solutions, gemmPref, heuristicResult));
|
|
CHECK_SOLUTION_FOUND(heuristicResult.size());
|
|
|
|
// Make sure to initialize every time when algo changes
|
|
CHECK_HIPBLASLT_ERROR(gemm.initialize(heuristicResult[0].algo, nullptr));
|
|
// Validation for solution running.
|
|
CHECK_HIPBLASLT_ERROR(gemm.run(stream));
|
|
|
|
CHECK_HIP_ERROR(hipFree(d_c));
|
|
CHECK_HIP_ERROR(hipFree(d_d));
|
|
CHECK_HIPBLASLT_ERROR(hipblasLtDestroy(handle));
|
|
CHECK_HIP_ERROR(hipStreamDestroy(stream));
|
|
}
|
|
|
|
void testing_aux_matmul_alg_get_attr_bad_arg(const Arguments& arg) {}
|
|
|
|
void testing_aux_matmul_alg_null_matmul(const Arguments& arg)
|
|
{
|
|
using InTypeA = hipblasLtHalf;
|
|
using InTypeB = hipblasLtHalf;
|
|
using OutType = hipblasLtHalf;
|
|
using AlphaType = hipblasLtFloat;
|
|
using BetaType = hipblasLtFloat;
|
|
|
|
hipStream_t stream;
|
|
hipblasLtHandle_t handle;
|
|
hipblasOperation_t trans_a = HIPBLAS_OP_N;
|
|
hipblasOperation_t trans_b = HIPBLAS_OP_T;
|
|
int64_t m = arg.M[0];
|
|
int64_t n = arg.N[0];
|
|
int64_t k = arg.K[0];
|
|
int64_t batch_count = 1;
|
|
float alpha = arg.alpha;
|
|
float beta = arg.beta;
|
|
void* d_a;
|
|
void* d_b;
|
|
void* d_c;
|
|
void* d_d;
|
|
void* a;
|
|
void* b;
|
|
void* c;
|
|
void* d;
|
|
|
|
CHECK_HIP_ERROR(hipStreamCreate(&stream));
|
|
CHECK_HIPBLASLT_ERROR(hipblasLtCreate(&handle));
|
|
CHECK_HIP_ERROR(hipMalloc(&d_a, m * k * batch_count * sizeof(InTypeA)));
|
|
CHECK_HIP_ERROR(hipMalloc(&d_b, n * k * batch_count * sizeof(InTypeB)));
|
|
CHECK_HIP_ERROR(hipMalloc(&d_c, m * n * batch_count * sizeof(OutType)));
|
|
CHECK_HIP_ERROR(hipMalloc(&d_d, m * n * batch_count * sizeof(OutType)));
|
|
CHECK_HIP_ERROR(hipHostMalloc(&a, m * k * batch_count * sizeof(InTypeA)));
|
|
CHECK_HIP_ERROR(hipHostMalloc(&b, n * k * batch_count * sizeof(InTypeB)));
|
|
CHECK_HIP_ERROR(hipHostMalloc(&c, m * n * batch_count * sizeof(OutType)));
|
|
CHECK_HIP_ERROR(hipHostMalloc(&d, m * n * batch_count * sizeof(OutType)));
|
|
|
|
CHECK_HIP_ERROR(hipMemcpyAsync(
|
|
d_a, a, m * k * batch_count * sizeof(InTypeA), hipMemcpyHostToDevice, stream));
|
|
CHECK_HIP_ERROR(hipMemcpyAsync(
|
|
d_b, b, n * k * batch_count * sizeof(InTypeB), hipMemcpyHostToDevice, stream));
|
|
CHECK_HIP_ERROR(hipMemcpyAsync(
|
|
d_c, c, m * n * batch_count * sizeof(OutType), hipMemcpyHostToDevice, stream));
|
|
|
|
hipblasLtMatrixLayout_t matA, matB, matC, matD;
|
|
CHECK_HIPBLASLT_ERROR(hipblasLtMatrixLayoutCreate(&matA, arg.a_type, m, k, m));
|
|
CHECK_HIPBLASLT_ERROR(hipblasLtMatrixLayoutCreate(&matB, arg.a_type, k, n, k));
|
|
CHECK_HIPBLASLT_ERROR(hipblasLtMatrixLayoutCreate(&matC, arg.a_type, m, n, m));
|
|
CHECK_HIPBLASLT_ERROR(hipblasLtMatrixLayoutCreate(&matD, arg.a_type, m, n, m));
|
|
|
|
hipblasLtMatmulDesc_t matmul;
|
|
CHECK_HIPBLASLT_ERROR(hipblasLtMatmulDescCreate(&matmul, arg.compute_type, arg.scale_type));
|
|
CHECK_HIPBLASLT_ERROR(hipblasLtMatmulDescSetAttribute(
|
|
matmul, HIPBLASLT_MATMUL_DESC_TRANSA, &trans_a, sizeof(int32_t)));
|
|
CHECK_HIPBLASLT_ERROR(hipblasLtMatmulDescSetAttribute(
|
|
matmul, HIPBLASLT_MATMUL_DESC_TRANSB, &trans_b, sizeof(int32_t)));
|
|
|
|
CHECK_HIPBLASLT_ERROR(hipblasLtMatmul(handle,
|
|
matmul,
|
|
&alpha,
|
|
d_a,
|
|
matA,
|
|
d_b,
|
|
matB,
|
|
&beta,
|
|
d_c,
|
|
matC,
|
|
d_d,
|
|
matD,
|
|
nullptr,
|
|
nullptr,
|
|
0,
|
|
0));
|
|
|
|
CHECK_HIP_ERROR(hipFree(a));
|
|
CHECK_HIP_ERROR(hipFree(b));
|
|
CHECK_HIP_ERROR(hipFree(c));
|
|
CHECK_HIP_ERROR(hipFree(d));
|
|
CHECK_HIP_ERROR(hipFree(d_a));
|
|
CHECK_HIP_ERROR(hipFree(d_b));
|
|
CHECK_HIP_ERROR(hipFree(d_c));
|
|
CHECK_HIP_ERROR(hipFree(d_d));
|
|
CHECK_HIPBLASLT_ERROR(hipblasLtMatmulDescDestroy(matmul));
|
|
CHECK_HIPBLASLT_ERROR(hipblasLtMatrixLayoutDestroy(matA));
|
|
CHECK_HIPBLASLT_ERROR(hipblasLtMatrixLayoutDestroy(matB));
|
|
CHECK_HIPBLASLT_ERROR(hipblasLtMatrixLayoutDestroy(matC));
|
|
CHECK_HIPBLASLT_ERROR(hipblasLtMatrixLayoutDestroy(matD));
|
|
CHECK_HIPBLASLT_ERROR(hipblasLtDestroy(handle));
|
|
CHECK_HIP_ERROR(hipStreamDestroy(stream));
|
|
}
|
|
|
|
void testing_aux_matmul_bad_ws_size(const Arguments& arg)
|
|
{
|
|
using InTypeA = hipblasLtHalf;
|
|
using InTypeB = hipblasLtHalf;
|
|
using OutType = hipblasLtHalf;
|
|
using AlphaType = hipblasLtFloat;
|
|
using BetaType = hipblasLtFloat;
|
|
|
|
hipStream_t stream;
|
|
hipblasLtHandle_t handle;
|
|
hipblasOperation_t trans_a = HIPBLAS_OP_N;
|
|
hipblasOperation_t trans_b = HIPBLAS_OP_N;
|
|
int64_t m = 2048;
|
|
int64_t n = 2048;
|
|
int64_t k = 2048;
|
|
int64_t batch_count = 1;
|
|
float alpha = arg.alpha;
|
|
float beta = arg.beta;
|
|
void* d_a;
|
|
void* d_b;
|
|
void* d_c;
|
|
void* d_d;
|
|
void* a;
|
|
void* b;
|
|
void* c;
|
|
void* d;
|
|
|
|
CHECK_HIP_ERROR(hipStreamCreate(&stream));
|
|
CHECK_HIPBLASLT_ERROR(hipblasLtCreate(&handle));
|
|
CHECK_HIP_ERROR(hipMalloc(&d_a, m * k * batch_count * sizeof(InTypeA)));
|
|
CHECK_HIP_ERROR(hipMalloc(&d_b, n * k * batch_count * sizeof(InTypeB)));
|
|
CHECK_HIP_ERROR(hipMalloc(&d_c, m * n * batch_count * sizeof(OutType)));
|
|
CHECK_HIP_ERROR(hipMalloc(&d_d, m * n * batch_count * sizeof(OutType)));
|
|
CHECK_HIP_ERROR(hipHostMalloc(&a, m * k * batch_count * sizeof(InTypeA)));
|
|
CHECK_HIP_ERROR(hipHostMalloc(&b, n * k * batch_count * sizeof(InTypeB)));
|
|
CHECK_HIP_ERROR(hipHostMalloc(&c, m * n * batch_count * sizeof(OutType)));
|
|
CHECK_HIP_ERROR(hipHostMalloc(&d, m * n * batch_count * sizeof(OutType)));
|
|
|
|
CHECK_HIP_ERROR(hipMemcpyAsync(
|
|
d_a, a, m * k * batch_count * sizeof(InTypeA), hipMemcpyHostToDevice, stream));
|
|
CHECK_HIP_ERROR(hipMemcpyAsync(
|
|
d_b, b, n * k * batch_count * sizeof(InTypeB), hipMemcpyHostToDevice, stream));
|
|
CHECK_HIP_ERROR(hipMemcpyAsync(
|
|
d_c, c, m * n * batch_count * sizeof(OutType), hipMemcpyHostToDevice, stream));
|
|
|
|
hipblasLtMatrixLayout_t matA, matB, matC, matD;
|
|
CHECK_HIPBLASLT_ERROR(hipblasLtMatrixLayoutCreate(&matA, arg.a_type, m, k, m));
|
|
CHECK_HIPBLASLT_ERROR(hipblasLtMatrixLayoutCreate(&matB, arg.a_type, k, n, k));
|
|
CHECK_HIPBLASLT_ERROR(hipblasLtMatrixLayoutCreate(&matC, arg.a_type, m, n, m));
|
|
CHECK_HIPBLASLT_ERROR(hipblasLtMatrixLayoutCreate(&matD, arg.a_type, m, n, m));
|
|
|
|
hipblasLtMatmulDesc_t matmul;
|
|
CHECK_HIPBLASLT_ERROR(hipblasLtMatmulDescCreate(&matmul, arg.compute_type, arg.scale_type));
|
|
CHECK_HIPBLASLT_ERROR(hipblasLtMatmulDescSetAttribute(
|
|
matmul, HIPBLASLT_MATMUL_DESC_TRANSA, &trans_a, sizeof(int32_t)));
|
|
CHECK_HIPBLASLT_ERROR(hipblasLtMatmulDescSetAttribute(
|
|
matmul, HIPBLASLT_MATMUL_DESC_TRANSB, &trans_b, sizeof(int32_t)));
|
|
|
|
hipblasLtMatmulPreference_t pref;
|
|
CHECK_HIPBLASLT_ERROR(hipblasLtMatmulPreferenceCreate(&pref));
|
|
size_t max_workspace_size = 128 * 1024 * 1024;
|
|
EXPECT_HIPBLAS_STATUS(
|
|
hipblasLtMatmulPreferenceSetAttribute(pref,
|
|
HIPBLASLT_MATMUL_PREF_MAX_WORKSPACE_BYTES,
|
|
&max_workspace_size,
|
|
sizeof(max_workspace_size)),
|
|
HIPBLAS_STATUS_SUCCESS);
|
|
const int request_solutions = 1000;
|
|
hipblasLtMatmulHeuristicResult_t heuristicResult[request_solutions];
|
|
int returnedAlgoCount = 0;
|
|
CHECK_HIPBLASLT_ERROR(hipblasLtMatmulAlgoGetHeuristic(handle,
|
|
matmul,
|
|
matA,
|
|
matB,
|
|
matC,
|
|
matD,
|
|
pref,
|
|
request_solutions,
|
|
heuristicResult,
|
|
&returnedAlgoCount));
|
|
|
|
void* d_ws;
|
|
CHECK_HIP_ERROR(hipMalloc(&d_ws, 1));
|
|
for(int i = 0; i < returnedAlgoCount; i++)
|
|
{
|
|
if(heuristicResult[i].workspaceSize > 0)
|
|
{
|
|
//The normal behavior with insufficient ws size would be:
|
|
//1. run normally without crash and return HIPBLAS_STATUS_SUCCESS
|
|
//2. return HIPBLAS_STATUS_INVALID_VALUE
|
|
auto status = hipblasLtMatmul(handle,
|
|
matmul,
|
|
&alpha,
|
|
d_a,
|
|
matA,
|
|
d_b,
|
|
matB,
|
|
&beta,
|
|
d_c,
|
|
matC,
|
|
d_d,
|
|
matD,
|
|
&heuristicResult[i].algo,
|
|
d_ws,
|
|
1,
|
|
stream);
|
|
CHECK_SUCCESS((status == HIPBLAS_STATUS_SUCCESS)
|
|
|| (status == HIPBLAS_STATUS_INVALID_VALUE));
|
|
}
|
|
}
|
|
CHECK_HIP_ERROR(hipFree(d_ws));
|
|
|
|
CHECK_HIP_ERROR(hipFree(a));
|
|
CHECK_HIP_ERROR(hipFree(b));
|
|
CHECK_HIP_ERROR(hipFree(c));
|
|
CHECK_HIP_ERROR(hipFree(d));
|
|
CHECK_HIP_ERROR(hipFree(d_a));
|
|
CHECK_HIP_ERROR(hipFree(d_b));
|
|
CHECK_HIP_ERROR(hipFree(d_c));
|
|
CHECK_HIP_ERROR(hipFree(d_d));
|
|
CHECK_HIPBLASLT_ERROR(hipblasLtMatmulPreferenceDestroy(pref));
|
|
CHECK_HIPBLASLT_ERROR(hipblasLtMatmulDescDestroy(matmul));
|
|
CHECK_HIPBLASLT_ERROR(hipblasLtMatrixLayoutDestroy(matA));
|
|
CHECK_HIPBLASLT_ERROR(hipblasLtMatrixLayoutDestroy(matB));
|
|
CHECK_HIPBLASLT_ERROR(hipblasLtMatrixLayoutDestroy(matC));
|
|
CHECK_HIPBLASLT_ERROR(hipblasLtMatrixLayoutDestroy(matD));
|
|
CHECK_HIPBLASLT_ERROR(hipblasLtDestroy(handle));
|
|
CHECK_HIP_ERROR(hipStreamDestroy(stream));
|
|
}
|
|
void testing_aux_matmul_pref_init_bad_arg(const Arguments& arg)
|
|
{
|
|
hipblasLtMatmulPreference_t pref;
|
|
size_t workspace_size = 0;
|
|
|
|
EXPECT_HIPBLAS_STATUS(hipblasLtMatmulPreferenceCreate(nullptr), HIPBLAS_STATUS_INVALID_VALUE);
|
|
}
|
|
|
|
void testing_aux_matmul_pref_init(const Arguments& arg)
|
|
{
|
|
hipblaslt_local_preference pref;
|
|
EXPECT_HIPBLAS_STATUS(pref.status(), HIPBLAS_STATUS_SUCCESS);
|
|
}
|
|
|
|
void testing_aux_mat_copy(const Arguments& arg)
|
|
{
|
|
hipblasLtMatmulDesc_t matmul_src;
|
|
CHECK_HIPBLASLT_ERROR(hipblasLtMatmulDescCreate(&matmul_src, arg.compute_type, arg.scale_type));
|
|
hipblasLtMatmulDesc_t matmul_dest;
|
|
CHECK_HIPBLASLT_ERROR(hipblasLtMatmulDescCreate(&matmul_dest, HIPBLAS_COMPUTE_32F, HIP_R_32F));
|
|
|
|
EXPECT_HIPBLAS_STATUS(hipblaslt_ext::copyMatmul(nullptr, matmul_dest),
|
|
HIPBLAS_STATUS_INVALID_VALUE);
|
|
EXPECT_HIPBLAS_STATUS(hipblaslt_ext::copyMatmul(matmul_src, nullptr),
|
|
HIPBLAS_STATUS_INVALID_VALUE);
|
|
EXPECT_HIPBLAS_STATUS(hipblaslt_ext::copyMatmul(matmul_src, matmul_dest),
|
|
HIPBLAS_STATUS_SUCCESS);
|
|
|
|
CHECK_HIPBLASLT_ERROR(hipblasLtMatmulDescDestroy(matmul_src));
|
|
CHECK_HIPBLASLT_ERROR(hipblasLtMatmulDescDestroy(matmul_dest));
|
|
}
|
|
|
|
#ifdef CODE_COVERAGE
|
|
inline void testing_aux_auxiliary_func(const Arguments& arg)
|
|
{
|
|
// Test gpu_arch_match
|
|
int deviceId;
|
|
hipDeviceProp_t deviceProperties;
|
|
static_cast<void>(hipGetDevice(&deviceId));
|
|
static_cast<void>(hipGetDeviceProperties(&deviceProperties, deviceId));
|
|
ASSERT_TRUE(gpu_arch_match(deviceProperties.gcnArchName, ""));
|
|
ASSERT_TRUE(gpu_arch_match(deviceProperties.gcnArchName, "\\d"));
|
|
|
|
// Test hipblas_status_to_string
|
|
ASSERT_TRUE(hipblas_status_to_string(HIPBLAS_STATUS_SUCCESS) == "HIPBLAS_STATUS_SUCCESS");
|
|
ASSERT_TRUE(hipblas_status_to_string(HIPBLAS_STATUS_NOT_INITIALIZED)
|
|
== "HIPBLAS_STATUS_NOT_INITIALIZED");
|
|
ASSERT_TRUE(hipblas_status_to_string(HIPBLAS_STATUS_ALLOC_FAILED)
|
|
== "HIPBLAS_STATUS_ALLOC_FAILED");
|
|
ASSERT_TRUE(hipblas_status_to_string(HIPBLAS_STATUS_INVALID_VALUE)
|
|
== "HIPBLAS_STATUS_INVALID_VALUE");
|
|
ASSERT_TRUE(hipblas_status_to_string(HIPBLAS_STATUS_MAPPING_ERROR)
|
|
== "HIPBLAS_STATUS_MAPPING_ERROR");
|
|
ASSERT_TRUE(hipblas_status_to_string(HIPBLAS_STATUS_EXECUTION_FAILED)
|
|
== "HIPBLAS_STATUS_EXECUTION_FAILED");
|
|
ASSERT_TRUE(hipblas_status_to_string(HIPBLAS_STATUS_INTERNAL_ERROR)
|
|
== "HIPBLAS_STATUS_INTERNAL_ERROR");
|
|
ASSERT_TRUE(hipblas_status_to_string(HIPBLAS_STATUS_NOT_SUPPORTED)
|
|
== "HIPBLAS_STATUS_NOT_SUPPORTED");
|
|
ASSERT_TRUE(hipblas_status_to_string(HIPBLAS_STATUS_ARCH_MISMATCH)
|
|
== "HIPBLAS_STATUS_ARCH_MISMATCH");
|
|
ASSERT_TRUE(hipblas_status_to_string(HIPBLAS_STATUS_INVALID_ENUM)
|
|
== "HIPBLAS_STATUS_INVALID_ENUM");
|
|
ASSERT_TRUE(hipblas_status_to_string(HIPBLAS_STATUS_UNKNOWN) == "HIPBLAS_STATUS_UNKNOWN");
|
|
ASSERT_TRUE(hipblas_status_to_string(static_cast<hipblasStatus_t>(12))
|
|
== "<undefined hipblasStatus_t value>");
|
|
|
|
// Test hipblas_operation_to_string
|
|
|
|
ASSERT_TRUE(hipblas_operation_to_string(HIPBLAS_OP_N) == "N");
|
|
ASSERT_TRUE(hipblas_operation_to_string(HIPBLAS_OP_T) == "T");
|
|
ASSERT_TRUE(hipblas_operation_to_string(HIPBLAS_OP_C) == "C");
|
|
ASSERT_TRUE(hipblas_operation_to_string(static_cast<hipblasOperation_t>(114)) == "invalid");
|
|
|
|
// Test char_to_hipblas_operation
|
|
ASSERT_TRUE(char_to_hipblas_operation('N') == HIPBLAS_OP_N);
|
|
ASSERT_TRUE(char_to_hipblas_operation('n') == HIPBLAS_OP_N);
|
|
ASSERT_TRUE(char_to_hipblas_operation('T') == HIPBLAS_OP_T);
|
|
ASSERT_TRUE(char_to_hipblas_operation('t') == HIPBLAS_OP_T);
|
|
ASSERT_TRUE(char_to_hipblas_operation('C') == HIPBLAS_OP_C);
|
|
ASSERT_TRUE(char_to_hipblas_operation('c') == HIPBLAS_OP_C);
|
|
ASSERT_TRUE(char_to_hipblas_operation('X') == HIPBLASLT_OPERATION_INVALID);
|
|
|
|
// Test char_to_hipblas_operation
|
|
ASSERT_TRUE(char_to_hipblas_operation('N') == HIPBLAS_OP_N);
|
|
ASSERT_TRUE(char_to_hipblas_operation('n') == HIPBLAS_OP_N);
|
|
ASSERT_TRUE(char_to_hipblas_operation('T') == HIPBLAS_OP_T);
|
|
ASSERT_TRUE(char_to_hipblas_operation('t') == HIPBLAS_OP_T);
|
|
ASSERT_TRUE(char_to_hipblas_operation('C') == HIPBLAS_OP_C);
|
|
ASSERT_TRUE(char_to_hipblas_operation('c') == HIPBLAS_OP_C);
|
|
|
|
// Test hip_datatype_to_string
|
|
ASSERT_TRUE(hip_datatype_to_string(HIP_R_32F) == "f32_r");
|
|
ASSERT_TRUE(hip_datatype_to_string(HIP_R_64F) == "f64_r");
|
|
ASSERT_TRUE(hip_datatype_to_string(HIP_R_16F) == "f16_r");
|
|
ASSERT_TRUE(hip_datatype_to_string(HIP_R_16BF) == "bf16_r");
|
|
ASSERT_TRUE(hip_datatype_to_string(HIP_R_8I) == "i8_r");
|
|
ASSERT_TRUE(hip_datatype_to_string(HIP_R_32I) == "i32_r");
|
|
ASSERT_TRUE(hip_datatype_to_string(HIP_R_8F_E4M3_FNUZ) == "f8_fnuz_r");
|
|
ASSERT_TRUE(hip_datatype_to_string(HIP_R_8F_E5M2_FNUZ) == "bf8_fnuz_r");
|
|
ASSERT_TRUE(hip_datatype_to_string(HIP_R_8F_E4M3) == "f8_r");
|
|
ASSERT_TRUE(hip_datatype_to_string(HIP_R_8F_E5M2) == "bf8_r");
|
|
ASSERT_TRUE(hip_datatype_to_string(static_cast<hipDataType>(HIP_R_6F_E2M3)) == "f6_r");
|
|
ASSERT_TRUE(hip_datatype_to_string(static_cast<hipDataType>(HIP_R_6F_E3M2)) == "bf6_r");
|
|
ASSERT_TRUE(hip_datatype_to_string(static_cast<hipDataType>(HIP_R_4F_E2M1)) == "f4_r");
|
|
|
|
// Test hipblas_computetype_to_string
|
|
hipblas_computetype_to_string(HIPBLAS_COMPUTE_16F);
|
|
ASSERT_TRUE(hipblas_computetype_to_string(HIPBLAS_COMPUTE_16F) == "f16_r");
|
|
ASSERT_TRUE(hipblas_computetype_to_string(HIPBLAS_COMPUTE_32F) == "f32_r");
|
|
ASSERT_TRUE(hipblas_computetype_to_string(HIPBLAS_COMPUTE_32F_FAST_TF32) == "xf32_r");
|
|
ASSERT_TRUE(hipblas_computetype_to_string(HIPBLAS_COMPUTE_64F) == "f64_r");
|
|
ASSERT_TRUE(hipblas_computetype_to_string(HIPBLAS_COMPUTE_32I) == "i32_r");
|
|
ASSERT_TRUE(hipblas_computetype_to_string(HIPBLAS_COMPUTE_32F_FAST_16F) == "f32_f16_r");
|
|
ASSERT_TRUE(hipblas_computetype_to_string(HIPBLAS_COMPUTE_32F_FAST_16BF) == "f32_bf16_r");
|
|
ASSERT_TRUE(hipblas_computetype_to_string(HIPBLAS_COMPUTE_64F_PEDANTIC)
|
|
== "non-supported compute type");
|
|
|
|
// Test string_to_hip_datatype
|
|
ASSERT_TRUE(string_to_hip_datatype("f8_fnuz_r") == HIP_R_8F_E4M3_FNUZ);
|
|
ASSERT_TRUE(string_to_hip_datatype("bf8_fnuz_r") == HIP_R_8F_E5M2_FNUZ);
|
|
ASSERT_TRUE(string_to_hip_datatype("f8_r") == HIP_R_8F_E4M3);
|
|
ASSERT_TRUE(string_to_hip_datatype("bf8_r") == HIP_R_8F_E5M2);
|
|
ASSERT_TRUE(string_to_hip_datatype("f32_r") == HIP_R_32F);
|
|
ASSERT_TRUE(string_to_hip_datatype("f64_r") == HIP_R_64F);
|
|
ASSERT_TRUE(string_to_hip_datatype("f16_r") == HIP_R_16F);
|
|
ASSERT_TRUE(string_to_hip_datatype("bf16_r") == HIP_R_16BF);
|
|
ASSERT_TRUE(string_to_hip_datatype("i8_r") == HIP_R_8I);
|
|
ASSERT_TRUE(string_to_hip_datatype("f6_r") == static_cast<hipDataType>(HIP_R_6F_E2M3));
|
|
ASSERT_TRUE(string_to_hip_datatype("bf6_r") == static_cast<hipDataType>(HIP_R_6F_E3M2));
|
|
ASSERT_TRUE(string_to_hip_datatype("f4_r") == static_cast<hipDataType>(HIP_R_4F_E2M1));
|
|
ASSERT_TRUE(string_to_hip_datatype("i32_r") == HIP_R_32I);
|
|
ASSERT_TRUE(string_to_hip_datatype("") == HIPBLASLT_DATATYPE_INVALID);
|
|
|
|
// Test string_to_hip_datatype_assert
|
|
string_to_hip_datatype_assert("f8_fnuz_r");
|
|
|
|
// Test string_to_hipblas_computetype
|
|
ASSERT_TRUE(string_to_hipblas_computetype("f32_r") == HIPBLAS_COMPUTE_32F);
|
|
ASSERT_TRUE(string_to_hipblas_computetype("xf32_r") == HIPBLAS_COMPUTE_32F_FAST_TF32);
|
|
ASSERT_TRUE(string_to_hipblas_computetype("f64_r") == HIPBLAS_COMPUTE_64F);
|
|
ASSERT_TRUE(string_to_hipblas_computetype("i32_r") == HIPBLAS_COMPUTE_32I);
|
|
ASSERT_TRUE(string_to_hipblas_computetype("f32_f16_r") == HIPBLAS_COMPUTE_32F_FAST_16F);
|
|
ASSERT_TRUE(string_to_hipblas_computetype("f32_bf16_r") == HIPBLAS_COMPUTE_32F_FAST_16BF);
|
|
ASSERT_TRUE(string_to_hipblas_computetype("") == HIPBLASLT_COMPUTE_TYPE_INVALID);
|
|
|
|
// Test string_to_hipblas_computetype_assert
|
|
string_to_hipblas_computetype_assert("f32_r");
|
|
|
|
// Test string_to_epilogue_type
|
|
ASSERT_TRUE(string_to_epilogue_type("HIPBLASLT_EPILOGUE_RELU") == HIPBLASLT_EPILOGUE_RELU);
|
|
ASSERT_TRUE(string_to_epilogue_type("HIPBLASLT_EPILOGUE_BIAS") == HIPBLASLT_EPILOGUE_BIAS);
|
|
ASSERT_TRUE(string_to_epilogue_type("HIPBLASLT_EPILOGUE_RELU_BIAS")
|
|
== HIPBLASLT_EPILOGUE_RELU_BIAS);
|
|
ASSERT_TRUE(string_to_epilogue_type("HIPBLASLT_EPILOGUE_GELU") == HIPBLASLT_EPILOGUE_GELU);
|
|
ASSERT_TRUE(string_to_epilogue_type("HIPBLASLT_EPILOGUE_GELU_BIAS")
|
|
== HIPBLASLT_EPILOGUE_GELU_BIAS);
|
|
ASSERT_TRUE(string_to_epilogue_type("HIPBLASLT_EPILOGUE_RELU_AUX")
|
|
== HIPBLASLT_EPILOGUE_RELU_AUX);
|
|
ASSERT_TRUE(string_to_epilogue_type("HIPBLASLT_EPILOGUE_RELU_AUX_BIAS")
|
|
== HIPBLASLT_EPILOGUE_RELU_AUX_BIAS);
|
|
ASSERT_TRUE(string_to_epilogue_type("HIPBLASLT_EPILOGUE_GELU_AUX")
|
|
== HIPBLASLT_EPILOGUE_GELU_AUX);
|
|
ASSERT_TRUE(string_to_epilogue_type("HIPBLASLT_EPILOGUE_GELU_AUX_BIAS")
|
|
== HIPBLASLT_EPILOGUE_GELU_AUX_BIAS);
|
|
ASSERT_TRUE(string_to_epilogue_type("HIPBLASLT_EPILOGUE_RELU_AUX_BIAS")
|
|
== HIPBLASLT_EPILOGUE_RELU_AUX_BIAS);
|
|
ASSERT_TRUE(string_to_epilogue_type("HIPBLASLT_EPILOGUE_DGELU") == HIPBLASLT_EPILOGUE_DGELU);
|
|
ASSERT_TRUE(string_to_epilogue_type("HIPBLASLT_EPILOGUE_DGELU_BGRAD")
|
|
== HIPBLASLT_EPILOGUE_DGELU_BGRAD);
|
|
ASSERT_TRUE(string_to_epilogue_type("HIPBLASLT_EPILOGUE_DRELU") == HIPBLASLT_EPILOGUE_DRELU);
|
|
ASSERT_TRUE(string_to_epilogue_type("HIPBLASLT_EPILOGUE_DRELU_BGRAD")
|
|
== HIPBLASLT_EPILOGUE_DRELU_BGRAD);
|
|
ASSERT_TRUE(string_to_epilogue_type("HIPBLASLT_EPILOGUE_BGRADA") == HIPBLASLT_EPILOGUE_BGRADA);
|
|
ASSERT_TRUE(string_to_epilogue_type("HIPBLASLT_EPILOGUE_BGRADB") == HIPBLASLT_EPILOGUE_BGRADB);
|
|
ASSERT_TRUE(string_to_epilogue_type("HIPBLASLT_EPILOGUE_SWISH_EXT")
|
|
== HIPBLASLT_EPILOGUE_SWISH_EXT);
|
|
ASSERT_TRUE(string_to_epilogue_type("HIPBLASLT_EPILOGUE_SWISH_BIAS_EXT")
|
|
== HIPBLASLT_EPILOGUE_SWISH_BIAS_EXT);
|
|
ASSERT_TRUE(string_to_epilogue_type("HIPBLASLT_EPILOGUE_CLAMP_EXT")
|
|
== HIPBLASLT_EPILOGUE_CLAMP_EXT);
|
|
ASSERT_TRUE(string_to_epilogue_type("HIPBLASLT_EPILOGUE_CLAMP_BIAS_EXT")
|
|
== HIPBLASLT_EPILOGUE_CLAMP_BIAS_EXT);
|
|
ASSERT_TRUE(string_to_epilogue_type("HIPBLASLT_EPILOGUE_CLAMP_AUX_EXT")
|
|
== HIPBLASLT_EPILOGUE_CLAMP_AUX_EXT);
|
|
ASSERT_TRUE(string_to_epilogue_type("HIPBLASLT_EPILOGUE_CLAMP_AUX_BIAS_EXT")
|
|
== HIPBLASLT_EPILOGUE_CLAMP_AUX_BIAS_EXT);
|
|
|
|
ASSERT_TRUE(string_to_epilogue_type("HIPBLASLT_EPILOGUE_DEFAULT")
|
|
== HIPBLASLT_EPILOGUE_DEFAULT);
|
|
ASSERT_TRUE(string_to_epilogue_type("test") == static_cast<hipblasLtEpilogue_t>(0));
|
|
|
|
// Test string_to_epilogue_type_assert
|
|
ASSERT_TRUE(string_to_epilogue_type_assert("HIPBLASLT_EPILOGUE_RELU")
|
|
== HIPBLASLT_EPILOGUE_RELU);
|
|
|
|
// Test hipblaslt_isnan
|
|
uint32_t other_type_value = 5;
|
|
ASSERT_FALSE(hipblaslt_isnan(other_type_value));
|
|
|
|
float non_integral_nan = std::numeric_limits<float>::quiet_NaN();
|
|
ASSERT_TRUE(hipblaslt_isnan(non_integral_nan));
|
|
|
|
hipblaslt_f8_fnuz arg_hipblaslt_f8_fnuz;
|
|
arg_hipblaslt_f8_fnuz.__x = 0x80;
|
|
ASSERT_TRUE(hipblaslt_isnan(arg_hipblaslt_f8_fnuz));
|
|
|
|
hipblaslt_bf8_fnuz arg_hipblaslt_bf8_fnuz;
|
|
arg_hipblaslt_bf8_fnuz.__x = 0x80;
|
|
ASSERT_TRUE(hipblaslt_isnan(arg_hipblaslt_bf8_fnuz));
|
|
|
|
hipblaslt_f8 arg_hipblaslt_f8;
|
|
arg_hipblaslt_f8.__x = 0x7f;
|
|
ASSERT_TRUE(hipblaslt_isnan(arg_hipblaslt_f8));
|
|
arg_hipblaslt_f8.__x = 0x80;
|
|
ASSERT_FALSE(hipblaslt_isnan(arg_hipblaslt_f8));
|
|
ASSERT_TRUE(arg_hipblaslt_f8.is_zero());
|
|
|
|
hipblaslt_bf8 arg_hipblaslt_bf8;
|
|
arg_hipblaslt_bf8.__x = 0x7d;
|
|
ASSERT_TRUE(hipblaslt_isnan(arg_hipblaslt_bf8));
|
|
|
|
hipblasLtHalf pos_inf = static_cast<hipblasLtHalf>(INFINITY);
|
|
ASSERT_TRUE(hipblaslt_isinf(pos_inf));
|
|
|
|
hipblasLtHalf nan = static_cast<hipblasLtHalf>(NAN);
|
|
ASSERT_TRUE(hipblaslt_isnan(nan));
|
|
}
|
|
|
|
inline void testing_aux_float8_func(const Arguments& arg)
|
|
{
|
|
_Float16 f16 = 2.0;
|
|
|
|
// hipblaslt_f8_fnuz (FNUZ E4M3): zero only 0x00; 0x80 is NaN (is_inf matches for legacy API).
|
|
{
|
|
hipblaslt_f8_fnuz v(f16);
|
|
ASSERT_TRUE(f16 == static_cast<_Float16>(v));
|
|
|
|
v.__x = 0x00;
|
|
ASSERT_TRUE(v.is_zero());
|
|
ASSERT_FALSE(v.is_nan());
|
|
ASSERT_FALSE(v.is_inf());
|
|
|
|
v.__x = 0x80;
|
|
ASSERT_FALSE(v.is_zero());
|
|
ASSERT_TRUE(v.is_nan());
|
|
ASSERT_TRUE(v.is_inf());
|
|
ASSERT_TRUE(hipblaslt_isnan(v));
|
|
|
|
v.__x = 0x38;
|
|
ASSERT_FALSE(v.is_zero());
|
|
ASSERT_FALSE(v.is_nan());
|
|
ASSERT_FALSE(v.is_inf());
|
|
|
|
hipblaslt_f8_fnuz c;
|
|
c = v;
|
|
ASSERT_TRUE(c.__x == v.__x);
|
|
}
|
|
|
|
// hipblaslt_f8 (OCP E4M3): ±0 = 0x00/0x80; canonical NaN = 0x7f/0xff; no Inf.
|
|
{
|
|
hipblaslt_f8 v(f16);
|
|
ASSERT_TRUE(f16 == static_cast<_Float16>(v));
|
|
|
|
v.__x = 0x00;
|
|
ASSERT_TRUE(v.is_zero());
|
|
ASSERT_FALSE(v.is_nan());
|
|
ASSERT_FALSE(v.is_inf());
|
|
|
|
v.__x = 0x80;
|
|
ASSERT_TRUE(v.is_zero());
|
|
ASSERT_FALSE(v.is_nan());
|
|
ASSERT_FALSE(v.is_inf());
|
|
|
|
v.__x = 0x7f;
|
|
ASSERT_FALSE(v.is_zero());
|
|
ASSERT_TRUE(v.is_nan());
|
|
ASSERT_FALSE(v.is_inf());
|
|
ASSERT_TRUE(hipblaslt_isnan(v));
|
|
|
|
v.__x = 0xff;
|
|
ASSERT_FALSE(v.is_zero());
|
|
ASSERT_TRUE(v.is_nan());
|
|
ASSERT_FALSE(v.is_inf());
|
|
|
|
v.__x = 0x2a;
|
|
ASSERT_FALSE(v.is_zero());
|
|
ASSERT_FALSE(v.is_nan());
|
|
ASSERT_FALSE(v.is_inf());
|
|
|
|
hipblaslt_f8 c = v;
|
|
ASSERT_TRUE(c.__x == v.__x);
|
|
}
|
|
|
|
// hipblaslt_bf8_fnuz (FNUZ E5M2): same sentinel pattern as f8_fnuz.
|
|
{
|
|
hipblaslt_bf8_fnuz v(f16);
|
|
ASSERT_TRUE(f16 == static_cast<_Float16>(v));
|
|
|
|
v.__x = 0x00;
|
|
ASSERT_TRUE(v.is_zero());
|
|
ASSERT_FALSE(v.is_nan());
|
|
ASSERT_FALSE(v.is_inf());
|
|
|
|
v.__x = 0x80;
|
|
ASSERT_FALSE(v.is_zero());
|
|
ASSERT_TRUE(v.is_nan());
|
|
ASSERT_TRUE(v.is_inf());
|
|
ASSERT_TRUE(hipblaslt_isnan(v));
|
|
|
|
v.__x = 0x14;
|
|
ASSERT_FALSE(v.is_zero());
|
|
ASSERT_FALSE(v.is_nan());
|
|
ASSERT_FALSE(v.is_inf());
|
|
|
|
hipblaslt_bf8_fnuz c = v;
|
|
ASSERT_TRUE(c.__x == v.__x);
|
|
}
|
|
|
|
// hipblaslt_bf8 (OCP E5M2): ±0; Inf 0x7c/0xfc; NaN when exp=max and mantissa non-zero.
|
|
{
|
|
hipblaslt_bf8 v(f16);
|
|
ASSERT_TRUE(f16 == static_cast<_Float16>(v));
|
|
|
|
v.__x = 0x00;
|
|
ASSERT_TRUE(v.is_zero());
|
|
ASSERT_FALSE(v.is_nan());
|
|
ASSERT_FALSE(v.is_inf());
|
|
|
|
v.__x = 0x80;
|
|
ASSERT_TRUE(v.is_zero());
|
|
ASSERT_FALSE(v.is_nan());
|
|
ASSERT_FALSE(v.is_inf());
|
|
|
|
v.__x = 0x7c;
|
|
ASSERT_FALSE(v.is_zero());
|
|
ASSERT_FALSE(v.is_nan());
|
|
ASSERT_TRUE(v.is_inf());
|
|
|
|
v.__x = 0xfc;
|
|
ASSERT_FALSE(v.is_zero());
|
|
ASSERT_FALSE(v.is_nan());
|
|
ASSERT_TRUE(v.is_inf());
|
|
|
|
for(int b : {0x7d, 0x7e, 0x7f, 0xfd, 0xfe, 0xff})
|
|
{
|
|
v.__x = static_cast<decltype(v.__x)>(b);
|
|
ASSERT_FALSE(v.is_zero());
|
|
ASSERT_TRUE(v.is_nan());
|
|
ASSERT_FALSE(v.is_inf());
|
|
ASSERT_TRUE(hipblaslt_isnan(v));
|
|
}
|
|
|
|
v.__x = 0x08;
|
|
ASSERT_FALSE(v.is_zero());
|
|
ASSERT_FALSE(v.is_nan());
|
|
ASSERT_FALSE(v.is_inf());
|
|
|
|
hipblaslt_bf8 c = v;
|
|
ASSERT_TRUE(c.__x == v.__x);
|
|
}
|
|
|
|
// namespace std functions
|
|
// Test hipblaslt_f8_fnuz sin function
|
|
hipblaslt_f8_fnuz f8_fnuz_sin_val(f16);
|
|
hipblaslt_f8_fnuz f8_fnuz_sin_val_r = std::sin(f8_fnuz_sin_val);
|
|
ASSERT_TRUE(f8_fnuz_sin_val_r == hipblaslt_f8_fnuz(sinf(float(f8_fnuz_sin_val))));
|
|
|
|
// Test hipblaslt_f8_fnuz cos function
|
|
hipblaslt_f8_fnuz f8_fnuz_cos_val(f16);
|
|
hipblaslt_f8_fnuz f8_fnuz_cos_val_r = std::cos(f8_fnuz_cos_val);
|
|
ASSERT_TRUE(f8_fnuz_cos_val_r == hipblaslt_f8_fnuz(cosf(float(f8_fnuz_cos_val))));
|
|
|
|
// Test hipblaslt_f8 sin function
|
|
hipblaslt_f8 f8_sin_val(f16);
|
|
hipblaslt_f8 f8_sin_val_r = std::sin(f8_sin_val);
|
|
ASSERT_TRUE(f8_sin_val_r == hipblaslt_f8(sinf(float(f8_sin_val))));
|
|
|
|
// Test hipblaslt_f8 cos function
|
|
hipblaslt_f8 f8_cos_val(f16);
|
|
hipblaslt_f8 f8_cos_val_r = std::cos(f8_cos_val);
|
|
ASSERT_TRUE(f8_cos_val_r == hipblaslt_f8(cosf(float(f8_cos_val))));
|
|
|
|
// Test hipblaslt_bf8_fnuz sin function
|
|
hipblaslt_bf8_fnuz bf8_fnuz_sin_val(f16);
|
|
hipblaslt_bf8_fnuz bf8_fnuz_sin_val_r = std::sin(bf8_fnuz_sin_val);
|
|
ASSERT_TRUE(bf8_fnuz_sin_val_r == hipblaslt_bf8_fnuz(sinf(float(bf8_fnuz_sin_val))));
|
|
|
|
// Test hipblaslt_bf8_fnuz cos function
|
|
hipblaslt_bf8_fnuz bf8_fnuz_cos_val(f16);
|
|
hipblaslt_bf8_fnuz bf8_fnuz_cos_val_r = std::cos(bf8_fnuz_cos_val);
|
|
ASSERT_TRUE(bf8_fnuz_cos_val_r == hipblaslt_bf8_fnuz(cosf(float(bf8_fnuz_cos_val))));
|
|
|
|
// Test hipblaslt_bf8 sin function
|
|
hipblaslt_bf8 bf8_sin_val(f16);
|
|
hipblaslt_bf8 bf8_sin_val_r = std::sin(bf8_sin_val);
|
|
ASSERT_TRUE(bf8_sin_val_r == hipblaslt_bf8(sinf(float(bf8_sin_val))));
|
|
|
|
// Test hipblaslt_bf8 cos function
|
|
hipblaslt_bf8 bf8_cos_val(f16);
|
|
hipblaslt_bf8 bf8_cos_val_r = std::cos(bf8_cos_val);
|
|
ASSERT_TRUE(bf8_cos_val_r == hipblaslt_bf8(cosf(float(bf8_cos_val))));
|
|
|
|
// Test hipblaslt_f8_fnuz real function
|
|
hipblaslt_f8_fnuz f8_fnuz_real_val(f16);
|
|
hipblaslt_f8_fnuz f8_fnuz_real_val_r = std::real(f8_fnuz_real_val);
|
|
ASSERT_TRUE(f8_fnuz_real_val_r == hipblaslt_f8_fnuz(std::real(float(f8_fnuz_real_val))));
|
|
|
|
// Test hipblaslt_f8 real function
|
|
hipblaslt_f8 f8_real_val(f16);
|
|
hipblaslt_f8 f8_real_val_r = std::real(f8_real_val);
|
|
ASSERT_TRUE(f8_real_val_r == hipblaslt_f8(std::real(float(f8_real_val))));
|
|
|
|
// Test hipblaslt_bf8_fnuz real function
|
|
hipblaslt_bf8_fnuz bf8_fnuz_real_val(f16);
|
|
hipblaslt_bf8_fnuz bf8_fnuz_real_val_r = std::real(bf8_fnuz_real_val);
|
|
ASSERT_TRUE(bf8_fnuz_real_val_r == hipblaslt_bf8_fnuz(std::real(float(bf8_fnuz_real_val))));
|
|
|
|
// Test hipblaslt_bf8 real function
|
|
hipblaslt_bf8 bf8_real_val(f16);
|
|
hipblaslt_bf8 bf8_real_val_r = std::real(bf8_real_val);
|
|
ASSERT_TRUE(bf8_real_val_r == hipblaslt_bf8(std::real(float(bf8_real_val))));
|
|
|
|
// Test hipblaslt_f8_fnuz ostream operator
|
|
hipblaslt_f8_fnuz f8_fnuz_stream_val(f16);
|
|
std::ostringstream f8_fnuz_stream;
|
|
f8_fnuz_stream << f8_fnuz_stream_val;
|
|
std::ostringstream f8_fnuz_expected;
|
|
f8_fnuz_expected << float(f8_fnuz_stream_val);
|
|
ASSERT_TRUE(f8_fnuz_stream.str() == f8_fnuz_expected.str());
|
|
|
|
// Test hipblaslt_f8 ostream operator
|
|
hipblaslt_f8 f8_stream_val(f16);
|
|
std::ostringstream f8_stream;
|
|
f8_stream << f8_stream_val;
|
|
std::ostringstream f8_expected;
|
|
f8_expected << float(f8_stream_val);
|
|
ASSERT_TRUE(f8_stream.str() == f8_expected.str());
|
|
|
|
// Test hipblaslt_bf8_fnuz ostream operator
|
|
hipblaslt_bf8_fnuz bf8_fnuz_stream_val(f16);
|
|
std::ostringstream bf8_fnuz_stream;
|
|
bf8_fnuz_stream << bf8_fnuz_stream_val;
|
|
std::ostringstream bf8_fnuz_expected;
|
|
bf8_fnuz_expected << float(bf8_fnuz_stream_val);
|
|
ASSERT_TRUE(bf8_fnuz_stream.str() == bf8_fnuz_expected.str());
|
|
|
|
// Test hipblaslt_bf8 ostream operator
|
|
hipblaslt_bf8 bf8_stream_val(f16);
|
|
std::ostringstream bf8_stream;
|
|
bf8_stream << bf8_stream_val;
|
|
std::ostringstream bf8_expected;
|
|
bf8_expected << float(bf8_stream_val);
|
|
ASSERT_TRUE(bf8_stream.str() == bf8_expected.str());
|
|
|
|
// Test code for hipblaslt_float8.h operator overloads
|
|
_Float16 f16_a = 2.5;
|
|
_Float16 f16_b = 1.5;
|
|
float float_val = 3.0f;
|
|
int32_t int_val = 4;
|
|
double double_val = 5.0;
|
|
|
|
// Test addition operators with mixed types (float + f8 types)
|
|
hipblaslt_f8_fnuz f8_fnuz_val(f16_a);
|
|
hipblaslt_f8 f8_val(f16_a);
|
|
hipblaslt_bf8_fnuz bf8_fnuz_val(f16_a);
|
|
hipblaslt_bf8 bf8_val(f16_a);
|
|
|
|
// Test float + f8 types
|
|
float result_f = float_val + f8_fnuz_val;
|
|
ASSERT_TRUE(result_f == (float_val + float(f8_fnuz_val)));
|
|
result_f = float_val + f8_val;
|
|
ASSERT_TRUE(result_f == (float_val + float(f8_val)));
|
|
result_f = float_val + bf8_fnuz_val;
|
|
ASSERT_TRUE(result_f == (float_val + float(bf8_fnuz_val)));
|
|
result_f = float_val + bf8_val;
|
|
ASSERT_TRUE(result_f == (float_val + float(bf8_val)));
|
|
|
|
// Test f8 types + float
|
|
result_f = f8_fnuz_val + float_val;
|
|
ASSERT_TRUE(result_f == (float(f8_fnuz_val) + float_val));
|
|
result_f = f8_val + float_val;
|
|
ASSERT_TRUE(result_f == (float(f8_val) + float_val));
|
|
result_f = bf8_fnuz_val + float_val;
|
|
ASSERT_TRUE(result_f == (float(bf8_fnuz_val) + float_val));
|
|
result_f = bf8_val + float_val;
|
|
ASSERT_TRUE(result_f == (float(bf8_val) + float_val));
|
|
|
|
// Test mixed f8 types addition (returns float)
|
|
result_f = f8_fnuz_val + bf8_fnuz_val;
|
|
ASSERT_TRUE(result_f == (float(f8_fnuz_val) + float(bf8_fnuz_val)));
|
|
result_f = f8_val + bf8_val;
|
|
ASSERT_TRUE(result_f == (float(f8_val) + float(bf8_val)));
|
|
result_f = bf8_fnuz_val + f8_fnuz_val;
|
|
ASSERT_TRUE(result_f == (float(bf8_fnuz_val) + float(f8_fnuz_val)));
|
|
result_f = bf8_val + f8_val;
|
|
ASSERT_TRUE(result_f == (float(bf8_val) + float(f8_val)));
|
|
|
|
// Test same type addition (returns same type)
|
|
hipblaslt_f8_fnuz f8_fnuz_b(f16_b);
|
|
hipblaslt_f8_fnuz f8_fnuz_result = f8_fnuz_val + f8_fnuz_b;
|
|
ASSERT_TRUE(f8_fnuz_result == hipblaslt_f8_fnuz(float(f8_fnuz_val) + float(f8_fnuz_b)));
|
|
|
|
hipblaslt_f8 f8_b(f16_b);
|
|
hipblaslt_f8 f8_result = f8_val + f8_b;
|
|
ASSERT_TRUE(f8_result == hipblaslt_f8(float(f8_val) + float(f8_b)));
|
|
|
|
hipblaslt_bf8_fnuz bf8_fnuz_b(f16_b);
|
|
hipblaslt_bf8_fnuz bf8_fnuz_result = bf8_fnuz_val + bf8_fnuz_b;
|
|
ASSERT_TRUE(bf8_fnuz_result == hipblaslt_bf8_fnuz(float(bf8_fnuz_val) + float(bf8_fnuz_b)));
|
|
|
|
hipblaslt_bf8 bf8_b(f16_b);
|
|
hipblaslt_bf8 bf8_result = bf8_val + bf8_b;
|
|
ASSERT_TRUE(bf8_result == hipblaslt_bf8(float(bf8_val) + float(bf8_b)));
|
|
|
|
// Test += operators
|
|
hipblaslt_f8_fnuz f8_fnuz_copy = f8_fnuz_val;
|
|
f8_fnuz_copy += f8_fnuz_b;
|
|
ASSERT_TRUE(f8_fnuz_copy == hipblaslt_f8_fnuz(float(f8_fnuz_val) + float(f8_fnuz_b)));
|
|
|
|
hipblaslt_f8 f8_copy = f8_val;
|
|
f8_copy += f8_b;
|
|
ASSERT_TRUE(f8_copy == hipblaslt_f8(float(f8_val) + float(f8_b)));
|
|
|
|
hipblaslt_bf8_fnuz bf8_fnuz_copy = bf8_fnuz_val;
|
|
bf8_fnuz_copy += bf8_fnuz_b;
|
|
ASSERT_TRUE(bf8_fnuz_copy == hipblaslt_bf8_fnuz(float(bf8_fnuz_val) + float(bf8_fnuz_b)));
|
|
|
|
hipblaslt_bf8 bf8_copy = bf8_val;
|
|
bf8_copy += bf8_b;
|
|
ASSERT_TRUE(bf8_copy == hipblaslt_bf8(float(bf8_val) + float(bf8_b)));
|
|
|
|
// Test multiplication operators (all return float)
|
|
// Same type multiplication
|
|
result_f = f8_fnuz_val * f8_fnuz_b;
|
|
ASSERT_TRUE(result_f == (float(f8_fnuz_val) * float(f8_fnuz_b)));
|
|
result_f = f8_val * f8_b;
|
|
ASSERT_TRUE(result_f == (float(f8_val) * float(f8_b)));
|
|
|
|
// Test float * f8 types
|
|
result_f = float_val * f8_fnuz_val;
|
|
ASSERT_TRUE(result_f == (float_val * float(f8_fnuz_val)));
|
|
result_f = float_val * f8_val;
|
|
ASSERT_TRUE(result_f == (float_val * float(f8_val)));
|
|
|
|
// Test f8 types * float
|
|
result_f = f8_fnuz_val * float_val;
|
|
ASSERT_TRUE(result_f == (float(f8_fnuz_val) * float_val));
|
|
result_f = f8_val * float_val;
|
|
ASSERT_TRUE(result_f == (float(f8_val) * float_val));
|
|
|
|
// Test int32_t * f8 types
|
|
result_f = int_val * f8_fnuz_val;
|
|
ASSERT_TRUE(result_f == ((float)int_val * float(f8_fnuz_val)));
|
|
result_f = int_val * f8_val;
|
|
ASSERT_TRUE(result_f == ((float)int_val * float(f8_val)));
|
|
|
|
// Test double * f8 types
|
|
result_f = double_val * f8_fnuz_val;
|
|
ASSERT_TRUE(result_f == ((float)double_val * float(f8_fnuz_val)));
|
|
result_f = double_val * f8_val;
|
|
ASSERT_TRUE(result_f == ((float)double_val * float(f8_val)));
|
|
|
|
// Test bf8 type multiplication tests
|
|
result_f = bf8_fnuz_val * bf8_fnuz_b;
|
|
ASSERT_TRUE(result_f == (float(bf8_fnuz_val) * float(bf8_fnuz_b)));
|
|
result_f = bf8_val * bf8_b;
|
|
ASSERT_TRUE(result_f == (float(bf8_val) * float(bf8_b)));
|
|
|
|
result_f = float_val * bf8_fnuz_val;
|
|
ASSERT_TRUE(result_f == (float_val * float(bf8_fnuz_val)));
|
|
result_f = float_val * bf8_val;
|
|
ASSERT_TRUE(result_f == (float_val * float(bf8_val)));
|
|
|
|
result_f = bf8_fnuz_val * float_val;
|
|
ASSERT_TRUE(result_f == (float(bf8_fnuz_val) * float_val));
|
|
result_f = bf8_val * float_val;
|
|
ASSERT_TRUE(result_f == (float(bf8_val) * float_val));
|
|
|
|
result_f = int_val * bf8_fnuz_val;
|
|
ASSERT_TRUE(result_f == ((float)int_val * float(bf8_fnuz_val)));
|
|
result_f = int_val * bf8_val;
|
|
ASSERT_TRUE(result_f == ((float)int_val * float(bf8_val)));
|
|
|
|
result_f = double_val * bf8_fnuz_val;
|
|
ASSERT_TRUE(result_f == ((float)double_val * float(bf8_fnuz_val)));
|
|
result_f = double_val * bf8_val;
|
|
ASSERT_TRUE(result_f == ((float)double_val * float(bf8_val)));
|
|
|
|
// Test Mixed f8 and bf8 multiplication
|
|
result_f = f8_fnuz_val * bf8_fnuz_val;
|
|
ASSERT_TRUE(result_f == (float(f8_fnuz_val) * float(bf8_fnuz_val)));
|
|
result_f = f8_val * bf8_val;
|
|
ASSERT_TRUE(result_f == (float(f8_val) * float(bf8_val)));
|
|
result_f = bf8_fnuz_val * f8_fnuz_val;
|
|
ASSERT_TRUE(result_f == (float(bf8_fnuz_val) * float(f8_fnuz_val)));
|
|
result_f = bf8_val * f8_val;
|
|
ASSERT_TRUE(result_f == (float(bf8_val) * float(f8_val)));
|
|
|
|
// Test comparison operators
|
|
// Equality operators
|
|
bool result_b = (f8_fnuz_val == f8_fnuz_b);
|
|
ASSERT_TRUE(result_b == (f8_fnuz_val.__x == f8_fnuz_b.__x));
|
|
result_b = (f8_val == f8_b);
|
|
ASSERT_TRUE(result_b == (f8_val.__x == f8_b.__x));
|
|
result_b = (bf8_fnuz_val == bf8_fnuz_b);
|
|
ASSERT_TRUE(result_b == (bf8_fnuz_val.__x == bf8_fnuz_b.__x));
|
|
result_b = (bf8_val == bf8_b);
|
|
ASSERT_TRUE(result_b == (bf8_val.__x == bf8_b.__x));
|
|
|
|
// Test Inequality operators
|
|
result_b = (f8_fnuz_val != f8_fnuz_b);
|
|
ASSERT_TRUE(result_b == (f8_fnuz_val.__x != f8_fnuz_b.__x));
|
|
result_b = (f8_val != f8_b);
|
|
ASSERT_TRUE(result_b == (f8_val.__x != f8_b.__x));
|
|
result_b = (bf8_fnuz_val != bf8_fnuz_b);
|
|
ASSERT_TRUE(result_b == (bf8_fnuz_val.__x != bf8_fnuz_b.__x));
|
|
result_b = (bf8_val != bf8_b);
|
|
ASSERT_TRUE(result_b == (bf8_val.__x != bf8_b.__x));
|
|
|
|
// Test Greater than or equal operators
|
|
result_b = (f8_fnuz_val >= f8_fnuz_b);
|
|
ASSERT_TRUE(result_b == (static_cast<float>(f8_fnuz_val) >= static_cast<float>(f8_fnuz_b)));
|
|
result_b = (f8_val >= f8_b);
|
|
ASSERT_TRUE(result_b == (static_cast<float>(f8_val) >= static_cast<float>(f8_b)));
|
|
|
|
// Test Greater than operators
|
|
result_b = (f8_fnuz_val > f8_fnuz_b);
|
|
ASSERT_TRUE(result_b == (static_cast<float>(f8_fnuz_val) > static_cast<float>(f8_fnuz_b)));
|
|
result_b = (f8_val > f8_b);
|
|
ASSERT_TRUE(result_b == (static_cast<float>(f8_val) > static_cast<float>(f8_b)));
|
|
}
|
|
|
|
inline void testing_aux_hipblaslt_ext_op_func(const Arguments& arg)
|
|
{
|
|
ASSERT_TRUE(hipblasltGetTotalGranularityValue()
|
|
== hipblasltClientPerformanceArgs::totalGranularity);
|
|
ASSERT_TRUE(hipblasltGetTilesPerCuValue() == hipblasltClientPerformanceArgs::tilesPerCu);
|
|
ASSERT_TRUE(hipblasltGetTile0Granularity() == hipblasltClientPerformanceArgs::tile0Granularity);
|
|
ASSERT_TRUE(hipblasltGetTile1Granularity() == hipblasltClientPerformanceArgs::tile1Granularity);
|
|
ASSERT_TRUE(hipblasltGetCuGranularity() == hipblasltClientPerformanceArgs::cuGranularity);
|
|
ASSERT_TRUE(hipblasltGetWaveGranularity() == hipblasltClientPerformanceArgs::waveGranularity);
|
|
ASSERT_TRUE(hipblasltGetCUs() == hipblasltClientPerformanceArgs::CUs);
|
|
ASSERT_TRUE(hipblasltGetMemWriteBytesD() == hipblasltClientPerformanceArgs::memWriteBytesD);
|
|
ASSERT_TRUE(hipblasltGetMemReadBytes() == hipblasltClientPerformanceArgs::memReadBytes);
|
|
}
|
|
|
|
inline void testing_aux_rocblaslt_utility_func(const Arguments& arg)
|
|
{
|
|
// Test basic prefix functionality
|
|
std::string result = prefix("TEST_LAYER", "test_caller");
|
|
|
|
// Check that result is not empty
|
|
ASSERT_TRUE(!result.empty());
|
|
|
|
// Check that result contains expected components
|
|
ASSERT_TRUE(result.find("[HIPBLASLT]") != std::string::npos);
|
|
ASSERT_TRUE(result.find("[TEST_LAYER]") != std::string::npos);
|
|
ASSERT_TRUE(result.find("[test_caller]") != std::string::npos);
|
|
|
|
// Check date format pattern (YYYY-MM-DD)
|
|
std::regex date_pattern(R"(\[\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\])");
|
|
ASSERT_TRUE(std::regex_search(result, date_pattern));
|
|
|
|
// Check process ID is included (numeric value in brackets)
|
|
std::regex pid_pattern(R"(\[\d+\])");
|
|
ASSERT_TRUE(std::regex_search(result, pid_pattern));
|
|
|
|
// Test with different layer and caller names
|
|
std::string result2 = prefix("ERROR", "function_name");
|
|
ASSERT_TRUE(result2.find("[ERROR]") != std::string::npos);
|
|
ASSERT_TRUE(result2.find("[function_name]") != std::string::npos);
|
|
|
|
// Test with empty strings (edge case)
|
|
std::string result3 = prefix("", "");
|
|
ASSERT_TRUE(result3.find("[]") != std::string::npos); // Should contain empty brackets
|
|
ASSERT_TRUE(result3.find("[HIPBLASLT]")
|
|
!= std::string::npos); // HIPBLASLT should always be present
|
|
|
|
// Test format consistency - two calls should have similar structure
|
|
std::string result4 = prefix("LAYER1", "caller1");
|
|
std::string result5 = prefix("LAYER2", "caller2");
|
|
|
|
// Both should contain HIPBLASLT
|
|
ASSERT_TRUE(result4.find("[HIPBLASLT]") != std::string::npos);
|
|
ASSERT_TRUE(result5.find("[HIPBLASLT]") != std::string::npos);
|
|
|
|
// Both should match the expected format pattern
|
|
std::regex full_pattern(
|
|
R"(\[\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\]\[HIPBLASLT\]\[\d+\]\[.*\]\[.*\])");
|
|
ASSERT_TRUE(std::regex_match(result4, full_pattern));
|
|
ASSERT_TRUE(std::regex_match(result5, full_pattern));
|
|
|
|
// Test hipDataType_to_string function
|
|
ASSERT_TRUE(std::string_view{hipDataType_to_string(HIP_R_16F)} == "R_16F");
|
|
ASSERT_TRUE(std::string_view{hipDataType_to_string(HIP_R_16BF)} == "R_16BF");
|
|
ASSERT_TRUE(std::string_view{hipDataType_to_string(HIP_R_32F)} == "R_32F");
|
|
ASSERT_TRUE(std::string_view{hipDataType_to_string(HIP_R_64F)} == "R_64F");
|
|
ASSERT_TRUE(std::string_view{hipDataType_to_string(HIP_R_8F_E4M3_FNUZ)} == "R_8F_E4M3_FNUZ");
|
|
ASSERT_TRUE(std::string_view{hipDataType_to_string(HIP_R_8F_E5M2_FNUZ)} == "R_8F_E5M2_FNUZ");
|
|
ASSERT_TRUE(std::string_view{hipDataType_to_string(HIP_R_8F_E4M3)} == "R_8F_E4M3");
|
|
ASSERT_TRUE(std::string_view{hipDataType_to_string(HIP_R_8F_E5M2)} == "R_8F_E5M2");
|
|
ASSERT_TRUE(std::string_view{hipDataType_to_string(HIP_R_8I)} == "R_8I");
|
|
ASSERT_TRUE(std::string_view{hipDataType_to_string(static_cast<hipDataType>(HIP_R_6F_E2M3))}
|
|
== "R_6F_E2M3");
|
|
ASSERT_TRUE(std::string_view{hipDataType_to_string(static_cast<hipDataType>(HIP_R_6F_E3M2))}
|
|
== "R_6F_E3M2");
|
|
ASSERT_TRUE(std::string_view{hipDataType_to_string(static_cast<hipDataType>(HIP_R_4F_E2M1))}
|
|
== "R_4F_E2M1");
|
|
ASSERT_TRUE(std::string_view{hipDataType_to_string(static_cast<hipDataType>(999))}
|
|
== "Invalid");
|
|
|
|
ASSERT_TRUE(std::string_view{hipDataType_to_bench_string(HIP_R_32F)} == "f32_r");
|
|
ASSERT_TRUE(std::string_view{hipDataType_to_bench_string(HIP_R_64F)} == "f64_r");
|
|
ASSERT_TRUE(std::string_view{hipDataType_to_bench_string(HIP_R_16F)} == "f16_r");
|
|
ASSERT_TRUE(std::string_view{hipDataType_to_bench_string(HIP_R_16BF)} == "bf16_r");
|
|
ASSERT_TRUE(std::string_view{hipDataType_to_bench_string(HIP_R_8I)} == "i8_r");
|
|
ASSERT_TRUE(std::string_view{hipDataType_to_bench_string(HIP_R_32I)} == "i32_r");
|
|
ASSERT_TRUE(std::string_view{hipDataType_to_bench_string(HIP_R_8F_E4M3_FNUZ)} == "f8_r");
|
|
ASSERT_TRUE(std::string_view{hipDataType_to_bench_string(HIP_R_8F_E5M2_FNUZ)} == "bf8_r");
|
|
ASSERT_TRUE(std::string_view{hipDataType_to_bench_string(HIP_R_8F_E4M3)} == "f8_r");
|
|
ASSERT_TRUE(std::string_view{hipDataType_to_bench_string(HIP_R_8F_E5M2)} == "bf8_r");
|
|
ASSERT_TRUE(std::string_view{hipDataType_to_bench_string(HIP_R_8F_E5M2_FNUZ)} == "bf8_r");
|
|
ASSERT_TRUE(
|
|
std::string_view{hipDataType_to_bench_string(static_cast<hipDataType>(HIP_R_6F_E2M3))}
|
|
== "f6_r");
|
|
ASSERT_TRUE(
|
|
std::string_view{hipDataType_to_bench_string(static_cast<hipDataType>(HIP_R_6F_E3M2))}
|
|
== "bf6_r");
|
|
ASSERT_TRUE(
|
|
std::string_view{hipDataType_to_bench_string(static_cast<hipDataType>(HIP_R_4F_E2M1))}
|
|
== "f4_r");
|
|
ASSERT_TRUE(std::string_view{
|
|
hipDataType_to_bench_string(static_cast<hipDataType>(HIP_R_4F_E2M1 + 1))}
|
|
== "invalid");
|
|
|
|
// Test rocblaslt_compute_type_to_string
|
|
ASSERT_TRUE(std::string_view{rocblaslt_compute_type_to_string(rocblaslt_compute_f16)}
|
|
== "COMPUTE_16F");
|
|
ASSERT_TRUE(std::string_view{rocblaslt_compute_type_to_string(rocblaslt_compute_f32)}
|
|
== "COMPUTE_32F");
|
|
ASSERT_TRUE(std::string_view{rocblaslt_compute_type_to_string(rocblaslt_compute_f32_fast_xf32)}
|
|
== "COMPUTE_32XF");
|
|
ASSERT_TRUE(std::string_view{rocblaslt_compute_type_to_string(rocblaslt_compute_f64)}
|
|
== "COMPUTE_64F");
|
|
ASSERT_TRUE(std::string_view{rocblaslt_compute_type_to_string(rocblaslt_compute_i32)}
|
|
== "COMPUTE_32I");
|
|
ASSERT_TRUE(std::string_view{rocblaslt_compute_type_to_string(rocblaslt_compute_f32_fast_f16)}
|
|
== "COMPUTE_32F_16F");
|
|
ASSERT_TRUE(std::string_view{rocblaslt_compute_type_to_string(rocblaslt_compute_f32_fast_bf16)}
|
|
== "COMPUTE_32F_16BF");
|
|
ASSERT_TRUE(
|
|
std::string_view{rocblaslt_compute_type_to_string(static_cast<rocblaslt_compute_type>(999))}
|
|
== "Invalid");
|
|
|
|
// Test rocblaslt_matrix_layout_attributes_to_string
|
|
ASSERT_TRUE(std::string_view{rocblaslt_matrix_layout_attributes_to_string(
|
|
ROCBLASLT_MATRIX_LAYOUT_BATCH_COUNT)}
|
|
== "MATRIX_LAYOUT_BATCH_COUNT");
|
|
ASSERT_TRUE(std::string_view{rocblaslt_matrix_layout_attributes_to_string(
|
|
ROCBLASLT_MATRIX_LAYOUT_STRIDED_BATCH_OFFSET)}
|
|
== "MATRIX_LAYOUT_STRIDED_BATCH_OFFSET");
|
|
ASSERT_TRUE(
|
|
std::string_view{rocblaslt_matrix_layout_attributes_to_string(ROCBLASLT_MATRIX_LAYOUT_TYPE)}
|
|
== "ROCBLASLT_MATRIX_LAYOUT_TYPE");
|
|
ASSERT_TRUE(std::string_view{
|
|
rocblaslt_matrix_layout_attributes_to_string(ROCBLASLT_MATRIX_LAYOUT_ORDER)}
|
|
== "ROCBLASLT_MATRIX_LAYOUT_ORDER");
|
|
ASSERT_TRUE(
|
|
std::string_view{rocblaslt_matrix_layout_attributes_to_string(ROCBLASLT_MATRIX_LAYOUT_ROWS)}
|
|
== "ROCBLASLT_MATRIX_LAYOUT_ROWS");
|
|
ASSERT_TRUE(
|
|
std::string_view{rocblaslt_matrix_layout_attributes_to_string(ROCBLASLT_MATRIX_LAYOUT_COLS)}
|
|
== "ROCBLASLT_MATRIX_LAYOUT_COLS");
|
|
ASSERT_TRUE(
|
|
std::string_view{rocblaslt_matrix_layout_attributes_to_string(ROCBLASLT_MATRIX_LAYOUT_LD)}
|
|
== "ROCBLASLT_MATRIX_LAYOUT_LD");
|
|
ASSERT_TRUE(
|
|
std::string_view{rocblaslt_matrix_layout_attributes_to_string(ROCBLASLT_MATRIX_LAYOUT_MAX)}
|
|
== "ROCBLASLT_MATRIX_LAYOUT_MAX");
|
|
ASSERT_TRUE(std::string_view{rocblaslt_matrix_layout_attributes_to_string(
|
|
static_cast<rocblaslt_matrix_layout_attribute_>(999))}
|
|
== "Invalid");
|
|
|
|
// Test rocblaslt_matmul_desc_attributes_to_string
|
|
ASSERT_TRUE(
|
|
std::string_view{rocblaslt_matmul_desc_attributes_to_string(ROCBLASLT_MATMUL_DESC_TRANSA)}
|
|
== "MATMUL_DESC_TRANSA");
|
|
ASSERT_TRUE(
|
|
std::string_view{rocblaslt_matmul_desc_attributes_to_string(ROCBLASLT_MATMUL_DESC_TRANSB)}
|
|
== "MATMUL_DESC_TRANSB");
|
|
ASSERT_TRUE(
|
|
std::string_view{rocblaslt_matmul_desc_attributes_to_string(ROCBLASLT_MATMUL_DESC_EPILOGUE)}
|
|
== "MATMUL_DESC_EPILOGUE");
|
|
ASSERT_TRUE(std::string_view{
|
|
rocblaslt_matmul_desc_attributes_to_string(ROCBLASLT_MATMUL_DESC_BIAS_POINTER)}
|
|
== "MATMUL_DESC_BIAS_POINTER");
|
|
ASSERT_TRUE(std::string_view{rocblaslt_matmul_desc_attributes_to_string(
|
|
ROCBLASLT_MATMUL_DESC_BIAS_DATA_TYPE)}
|
|
== "MATMUL_DESC_BIAS_DATA_TYPE");
|
|
ASSERT_TRUE(std::string_view{rocblaslt_matmul_desc_attributes_to_string(
|
|
ROCBLASLT_MATMUL_DESC_A_SCALE_POINTER)}
|
|
== "MATMUL_DESC_A_SCALE_POINTER");
|
|
ASSERT_TRUE(std::string_view{rocblaslt_matmul_desc_attributes_to_string(
|
|
ROCBLASLT_MATMUL_DESC_B_SCALE_POINTER)}
|
|
== "MATMUL_DESC_B_SCALE_POINTER");
|
|
ASSERT_TRUE(std::string_view{rocblaslt_matmul_desc_attributes_to_string(
|
|
ROCBLASLT_MATMUL_DESC_C_SCALE_POINTER)}
|
|
== "MATMUL_DESC_C_SCALE_POINTER");
|
|
ASSERT_TRUE(std::string_view{rocblaslt_matmul_desc_attributes_to_string(
|
|
ROCBLASLT_MATMUL_DESC_D_SCALE_POINTER)}
|
|
== "MATMUL_DESC_D_SCALE_POINTER");
|
|
ASSERT_TRUE(std::string_view{rocblaslt_matmul_desc_attributes_to_string(
|
|
ROCBLASLT_MATMUL_DESC_EPILOGUE_AUX_POINTER)}
|
|
== "MATMUL_DESC_EPILOGUE_AUX_POINTER");
|
|
ASSERT_TRUE(std::string_view{rocblaslt_matmul_desc_attributes_to_string(
|
|
ROCBLASLT_MATMUL_DESC_EPILOGUE_AUX_LD)}
|
|
== "MATMUL_DESC_EPILOGUE_AUX_LD");
|
|
ASSERT_TRUE(std::string_view{rocblaslt_matmul_desc_attributes_to_string(
|
|
ROCBLASLT_MATMUL_DESC_EPILOGUE_AUX_BATCH_STRIDE)}
|
|
== "MATMUL_DESC_EPILOGUE_AUX_BATCH_STRIDE");
|
|
ASSERT_TRUE(std::string_view{
|
|
rocblaslt_matmul_desc_attributes_to_string(ROCBLASLT_MATMUL_DESC_POINTER_MODE)}
|
|
== "MATMUL_DESC_POINTER_MODE");
|
|
ASSERT_TRUE(std::string_view{rocblaslt_matmul_desc_attributes_to_string(
|
|
ROCBLASLT_MATMUL_DESC_AMAX_D_POINTER)}
|
|
== "MATMUL_DESC_AMAX_D_POINTER");
|
|
ASSERT_TRUE(std::string_view{rocblaslt_matmul_desc_attributes_to_string(
|
|
ROCBLASLT_MATMUL_DESC_EPILOGUE_AUX_DATA_TYPE)}
|
|
== "MATMUL_DESC_EPILOGUE_AUX_DATA_TYPE");
|
|
ASSERT_TRUE(std::string_view{rocblaslt_matmul_desc_attributes_to_string(
|
|
ROCBLASLT_MATMUL_DESC_COMPUTE_INPUT_TYPE_A_EXT)}
|
|
== "MATMUL_DESC_COMPUTE_INPUT_TYPE_A_EXT");
|
|
ASSERT_TRUE(std::string_view{rocblaslt_matmul_desc_attributes_to_string(
|
|
ROCBLASLT_MATMUL_DESC_COMPUTE_INPUT_TYPE_B_EXT)}
|
|
== "MATMUL_DESC_COMPUTE_INPUT_TYPE_B_EXT");
|
|
ASSERT_TRUE(std::string_view{rocblaslt_matmul_desc_attributes_to_string(
|
|
static_cast<rocblaslt_matmul_desc_attributes>(999))}
|
|
== "Invalid");
|
|
|
|
// Test hipblasOperation_to_string
|
|
ASSERT_TRUE(std::string_view{hipblasOperation_to_string(HIPBLAS_OP_N)} == "OP_N");
|
|
ASSERT_TRUE(std::string_view{hipblasOperation_to_string(HIPBLAS_OP_T)} == "OP_T");
|
|
ASSERT_TRUE(std::string_view{hipblasOperation_to_string(HIPBLAS_OP_C)} == "OP_C");
|
|
ASSERT_TRUE(std::string_view{hipblasOperation_to_string(static_cast<hipblasOperation_t>(999))}
|
|
== "Invalid");
|
|
|
|
// Test rocblaslt_layer_mode2string
|
|
ASSERT_TRUE(std::string_view{rocblaslt_layer_mode2string(rocblaslt_layer_mode_none)} == "None");
|
|
ASSERT_TRUE(std::string_view{rocblaslt_layer_mode2string(rocblaslt_layer_mode_log_error)}
|
|
== "Error");
|
|
ASSERT_TRUE(std::string_view{rocblaslt_layer_mode2string(rocblaslt_layer_mode_log_trace)}
|
|
== "Trace");
|
|
ASSERT_TRUE(std::string_view{rocblaslt_layer_mode2string(rocblaslt_layer_mode_log_hints)}
|
|
== "Hints");
|
|
ASSERT_TRUE(std::string_view{rocblaslt_layer_mode2string(rocblaslt_layer_mode_log_info)}
|
|
== "Info");
|
|
ASSERT_TRUE(std::string_view{rocblaslt_layer_mode2string(rocblaslt_layer_mode_log_api)}
|
|
== "Api");
|
|
ASSERT_TRUE(std::string_view{rocblaslt_layer_mode2string(rocblaslt_layer_mode_log_bench)}
|
|
== "Bench");
|
|
ASSERT_TRUE(std::string_view{rocblaslt_layer_mode2string(rocblaslt_layer_mode_log_profile)}
|
|
== "Profile");
|
|
ASSERT_TRUE(
|
|
std::string_view{rocblaslt_layer_mode2string(rocblaslt_layer_mode_log_extended_profile)}
|
|
== "ExtendedProfile");
|
|
ASSERT_TRUE(
|
|
std::string_view{rocblaslt_layer_mode2string(static_cast<rocblaslt_layer_mode>(999))}
|
|
== "Invalid");
|
|
|
|
// Test rocblaslt_epilogue_to_string
|
|
ASSERT_TRUE(std::string_view{rocblaslt_epilogue_to_string(ROCBLASLT_EPILOGUE_DEFAULT)}
|
|
== "EPILOGUE_DEFAULT");
|
|
ASSERT_TRUE(std::string_view{rocblaslt_epilogue_to_string(ROCBLASLT_EPILOGUE_RELU)}
|
|
== "EPILOGUE_RELU");
|
|
ASSERT_TRUE(std::string_view{rocblaslt_epilogue_to_string(ROCBLASLT_EPILOGUE_BIAS)}
|
|
== "EPILOGUE_BIAS");
|
|
ASSERT_TRUE(std::string_view{rocblaslt_epilogue_to_string(ROCBLASLT_EPILOGUE_RELU_BIAS)}
|
|
== "EPILOGUE_RELU_BIAS");
|
|
ASSERT_TRUE(std::string_view{rocblaslt_epilogue_to_string(ROCBLASLT_EPILOGUE_GELU)}
|
|
== "EPILOGUE_GELU");
|
|
ASSERT_TRUE(std::string_view{rocblaslt_epilogue_to_string(ROCBLASLT_EPILOGUE_DGELU)}
|
|
== "EPILOGUE_DGELU");
|
|
ASSERT_TRUE(std::string_view{rocblaslt_epilogue_to_string(ROCBLASLT_EPILOGUE_DRELU)}
|
|
== "EPILOGUE_DRELU");
|
|
ASSERT_TRUE(std::string_view{rocblaslt_epilogue_to_string(ROCBLASLT_EPILOGUE_GELU_BIAS)}
|
|
== "EPILOGUE_GELU_BIAS");
|
|
ASSERT_TRUE(std::string_view{rocblaslt_epilogue_to_string(ROCBLASLT_EPILOGUE_GELU_AUX)}
|
|
== "EPILOGUE_GELU_AUX");
|
|
ASSERT_TRUE(std::string_view{rocblaslt_epilogue_to_string(ROCBLASLT_EPILOGUE_GELU_AUX_BIAS)}
|
|
== "EPILOGUE_GELU_AUX_BIAS");
|
|
ASSERT_TRUE(std::string_view{rocblaslt_epilogue_to_string(ROCBLASLT_EPILOGUE_DGELU_BGRAD)}
|
|
== "EPILOGUE_DGELU_BGRAD");
|
|
ASSERT_TRUE(std::string_view{rocblaslt_epilogue_to_string(ROCBLASLT_EPILOGUE_BGRADA)}
|
|
== "EPILOGUE_BGRADA");
|
|
ASSERT_TRUE(std::string_view{rocblaslt_epilogue_to_string(ROCBLASLT_EPILOGUE_BGRADB)}
|
|
== "EPILOGUE_BGRADB");
|
|
ASSERT_TRUE(std::string_view{rocblaslt_epilogue_to_string(ROCBLASLT_EPILOGUE_DRELU_BGRAD)}
|
|
== "EPILOGUE_DRELU_BGRAD");
|
|
ASSERT_TRUE(std::string_view{rocblaslt_epilogue_to_string(ROCBLASLT_EPILOGUE_SWISH_EXT)}
|
|
== "EPILOGUE_SWISH_EXT");
|
|
ASSERT_TRUE(std::string_view{rocblaslt_epilogue_to_string(ROCBLASLT_EPILOGUE_SWISH_BIAS_EXT)}
|
|
== "EPILOGUE_SWISH_BIAS_EXT");
|
|
ASSERT_TRUE(std::string_view{rocblaslt_epilogue_to_string(static_cast<rocblaslt_epilogue>(999))}
|
|
== "Invalid epilogue");
|
|
|
|
// Test all valid rocblaslt_compute_type values
|
|
ASSERT_TRUE(std::string_view{rocblaslt_compute_type_string(rocblaslt_compute_f16)} == "f16_r");
|
|
ASSERT_TRUE(std::string_view{rocblaslt_compute_type_string(rocblaslt_compute_f32)} == "f32_r");
|
|
ASSERT_TRUE(std::string_view{rocblaslt_compute_type_string(rocblaslt_compute_f32_fast_xf32)}
|
|
== "xf32_r");
|
|
ASSERT_TRUE(std::string_view{rocblaslt_compute_type_string(rocblaslt_compute_i32)} == "i32_r");
|
|
ASSERT_TRUE(std::string_view{rocblaslt_compute_type_string(rocblaslt_compute_f64)} == "f64_r");
|
|
ASSERT_TRUE(std::string_view{rocblaslt_compute_type_string(rocblaslt_compute_f32_fast_f16)}
|
|
== "f32_f16_r");
|
|
ASSERT_TRUE(std::string_view{rocblaslt_compute_type_string(rocblaslt_compute_f32_fast_bf16)}
|
|
== "f32_bf16_r");
|
|
ASSERT_TRUE(std::string_view{rocblaslt_compute_type_string(rocblaslt_compute_f32_fast_f8)}
|
|
== "f32_f8_r");
|
|
ASSERT_TRUE(std::string_view{rocblaslt_compute_type_string(rocblaslt_compute_f32_fast_f8_fnuz)}
|
|
== "f32_f8_fnuz_r");
|
|
ASSERT_TRUE(std::string_view{rocblaslt_compute_type_string(rocblaslt_compute_f32_fast_bf8)}
|
|
== "f32_bf8_fnuz_r");
|
|
ASSERT_TRUE(std::string_view{rocblaslt_compute_type_string(rocblaslt_compute_f32_fast_bf8_fnuz)}
|
|
== "f32_bf8_r");
|
|
ASSERT_TRUE(std::string_view{rocblaslt_compute_type_string(rocblaslt_compute_f32_fast_f8bf8)}
|
|
== "f32_f8bf8_r");
|
|
ASSERT_TRUE(
|
|
std::string_view{rocblaslt_compute_type_string(rocblaslt_compute_f32_fast_f8bf8_fnuz)}
|
|
== "f32_f8bf8_fnuz_r");
|
|
ASSERT_TRUE(std::string_view{rocblaslt_compute_type_string(rocblaslt_compute_f32_fast_bf8f8)}
|
|
== "f32_bf8f8_r");
|
|
ASSERT_TRUE(
|
|
std::string_view{rocblaslt_compute_type_string(rocblaslt_compute_f32_fast_bf8f8_fnuz)}
|
|
== "f32_bf8f8_fnuz_r");
|
|
ASSERT_TRUE(
|
|
std::string_view{rocblaslt_compute_type_string(static_cast<rocblaslt_compute_type>(999))}
|
|
== "invalidType");
|
|
|
|
// Test rocblaslt_matrix_layout_to_string function
|
|
// Create test matrix layout structures
|
|
_rocblaslt_matrix_layout mat1, mat2, mat3, mat4;
|
|
|
|
// Test case 1: Single batch matrix (batch_count <= 1)
|
|
mat1.type = HIP_R_32F;
|
|
mat1.m = 128;
|
|
mat1.n = 256;
|
|
mat1.ld = 128;
|
|
mat1.batch_count = 1;
|
|
mat1.batch_stride = 0;
|
|
|
|
std::string mat1_result = rocblaslt_matrix_layout_to_string(&mat1);
|
|
ASSERT_TRUE(!mat1_result.empty());
|
|
ASSERT_TRUE(mat1_result.find("[type=R_32F") != std::string::npos);
|
|
ASSERT_TRUE(mat1_result.find("rows=128") != std::string::npos);
|
|
ASSERT_TRUE(mat1_result.find("cols=256") != std::string::npos);
|
|
ASSERT_TRUE(mat1_result.find("ld=128") != std::string::npos);
|
|
// Should NOT contain batch_count and batch_stride for single batch
|
|
ASSERT_TRUE(mat1_result.find("batch_count") == std::string::npos);
|
|
ASSERT_TRUE(mat1_result.find("batch_stride") == std::string::npos);
|
|
|
|
// Test case 2: Batch matrix (batch_count > 1)
|
|
mat2.type = HIP_R_16F;
|
|
mat2.m = 64;
|
|
mat2.n = 128;
|
|
mat2.ld = 64;
|
|
mat2.batch_count = 4;
|
|
mat2.batch_stride = 8192;
|
|
|
|
std::string mat2_result = rocblaslt_matrix_layout_to_string(&mat2);
|
|
ASSERT_TRUE(!mat2_result.empty());
|
|
ASSERT_TRUE(mat2_result.find("[type=R_16F") != std::string::npos);
|
|
ASSERT_TRUE(mat2_result.find("rows=64") != std::string::npos);
|
|
ASSERT_TRUE(mat2_result.find("cols=128") != std::string::npos);
|
|
ASSERT_TRUE(mat2_result.find("ld=64") != std::string::npos);
|
|
// Should contain batch_count and batch_stride for batch matrix
|
|
ASSERT_TRUE(mat2_result.find("batch_count=4") != std::string::npos);
|
|
ASSERT_TRUE(mat2_result.find("batch_stride=8192") != std::string::npos);
|
|
|
|
// Test case 3: Zero batch count
|
|
mat3.type = HIP_R_64F;
|
|
mat3.m = 32;
|
|
mat3.n = 64;
|
|
mat3.ld = 32;
|
|
mat3.batch_count = 0;
|
|
mat3.batch_stride = 0;
|
|
|
|
std::string mat3_result = rocblaslt_matrix_layout_to_string(&mat3);
|
|
ASSERT_TRUE(!mat3_result.empty());
|
|
ASSERT_TRUE(mat3_result.find("[type=R_64F") != std::string::npos);
|
|
ASSERT_TRUE(mat3_result.find("rows=32") != std::string::npos);
|
|
ASSERT_TRUE(mat3_result.find("cols=64") != std::string::npos);
|
|
ASSERT_TRUE(mat3_result.find("ld=32") != std::string::npos);
|
|
// batch_count <= 1, so should NOT contain batch info
|
|
ASSERT_TRUE(mat3_result.find("batch_count") == std::string::npos);
|
|
ASSERT_TRUE(mat3_result.find("batch_stride") == std::string::npos);
|
|
|
|
// Test case 4: Different data types
|
|
mat4.type = HIP_R_8F_E4M3_FNUZ;
|
|
mat4.m = 16;
|
|
mat4.n = 32;
|
|
mat4.ld = 16;
|
|
mat4.batch_count = 8;
|
|
mat4.batch_stride = 512;
|
|
|
|
std::string mat4_result = rocblaslt_matrix_layout_to_string(&mat4);
|
|
ASSERT_TRUE(!mat4_result.empty());
|
|
ASSERT_TRUE(mat4_result.find("[type=R_8F_E4M3_FNUZ") != std::string::npos);
|
|
ASSERT_TRUE(mat4_result.find("rows=16") != std::string::npos);
|
|
ASSERT_TRUE(mat4_result.find("cols=32") != std::string::npos);
|
|
ASSERT_TRUE(mat4_result.find("ld=16") != std::string::npos);
|
|
ASSERT_TRUE(mat4_result.find("batch_count=8") != std::string::npos);
|
|
ASSERT_TRUE(mat4_result.find("batch_stride=512") != std::string::npos);
|
|
|
|
// Test format consistency - all results should start with '[' and end with ']'
|
|
ASSERT_TRUE(mat1_result.front() == '[' && mat1_result.back() == ']');
|
|
ASSERT_TRUE(mat2_result.front() == '[' && mat2_result.back() == ']');
|
|
ASSERT_TRUE(mat3_result.front() == '[' && mat3_result.back() == ']');
|
|
ASSERT_TRUE(mat4_result.front() == '[' && mat4_result.back() == ']');
|
|
|
|
// Test edge case: Large dimensions
|
|
_rocblaslt_matrix_layout mat_large;
|
|
mat_large.type = HIP_R_16BF;
|
|
mat_large.m = 4096;
|
|
mat_large.n = 8192;
|
|
mat_large.ld = 4096;
|
|
mat_large.batch_count = 16;
|
|
mat_large.batch_stride = 33554432; // 4096 * 8192
|
|
|
|
std::string result_large = rocblaslt_matrix_layout_to_string(&mat_large);
|
|
ASSERT_TRUE(!result_large.empty());
|
|
ASSERT_TRUE(result_large.find("rows=4096") != std::string::npos);
|
|
ASSERT_TRUE(result_large.find("cols=8192") != std::string::npos);
|
|
ASSERT_TRUE(result_large.find("batch_count=16") != std::string::npos);
|
|
ASSERT_TRUE(result_large.find("batch_stride=33554432") != std::string::npos);
|
|
|
|
// Test rocblaslt_matmul_desc_to_string function
|
|
// Create test matmul descriptor structures
|
|
_rocblaslt_matmul_desc desc1, desc2, desc3, desc4;
|
|
|
|
// Test case 1: No bias, no epilogue extension (simplest case)
|
|
desc1.compute_type = rocblaslt_compute_f32;
|
|
desc1.scale_type = HIP_R_32F;
|
|
desc1.op_A = HIPBLAS_OP_N;
|
|
desc1.op_B = HIPBLAS_OP_T;
|
|
desc1.epilogue = ROCBLASLT_EPILOGUE_DEFAULT;
|
|
desc1.bias = nullptr;
|
|
desc1.bias_type = HIPBLASLT_DATATYPE_INVALID;
|
|
desc1.aux_type = HIPBLASLT_DATATYPE_INVALID;
|
|
desc1.e = nullptr;
|
|
desc1.lde = 0;
|
|
|
|
std::string desc_result1 = rocblaslt_matmul_desc_to_string(&desc1);
|
|
ASSERT_TRUE(!desc_result1.empty());
|
|
ASSERT_TRUE(desc_result1.find("[computeType=COMPUTE_32F") != std::string::npos);
|
|
ASSERT_TRUE(desc_result1.find("scaleType=R_32F") != std::string::npos);
|
|
ASSERT_TRUE(desc_result1.find("transA=OP_N") != std::string::npos);
|
|
ASSERT_TRUE(desc_result1.find("transB=OP_T") != std::string::npos);
|
|
ASSERT_TRUE(desc_result1.find("epilogue=EPILOGUE_DEFAULT") != std::string::npos);
|
|
ASSERT_TRUE(desc_result1.find("biasPointer=0x") != std::string::npos);
|
|
// Should NOT contain epilogue aux or bias type info
|
|
ASSERT_TRUE(desc_result1.find("epilogueAuxPointer") == std::string::npos);
|
|
ASSERT_TRUE(desc_result1.find("biasType") == std::string::npos);
|
|
ASSERT_TRUE(desc_result1.front() == '[' && desc_result1.back() == ']');
|
|
|
|
// Test case 2: With bias, no epilogue extension
|
|
desc2.compute_type = rocblaslt_compute_f16;
|
|
desc2.scale_type = HIP_R_16F;
|
|
desc2.op_A = HIPBLAS_OP_T;
|
|
desc2.op_B = HIPBLAS_OP_N;
|
|
desc2.epilogue = ROCBLASLT_EPILOGUE_BIAS;
|
|
desc2.bias = reinterpret_cast<void*>(0x12345678);
|
|
desc2.bias_type = HIP_R_16F;
|
|
desc2.aux_type = HIPBLASLT_DATATYPE_INVALID;
|
|
desc2.e = nullptr;
|
|
desc2.lde = 0;
|
|
|
|
std::string desc_result2 = rocblaslt_matmul_desc_to_string(&desc2);
|
|
ASSERT_TRUE(!desc_result2.empty());
|
|
ASSERT_TRUE(desc_result2.find("computeType=COMPUTE_16F") != std::string::npos);
|
|
ASSERT_TRUE(desc_result2.find("scaleType=R_16F") != std::string::npos);
|
|
ASSERT_TRUE(desc_result2.find("transA=OP_T") != std::string::npos);
|
|
ASSERT_TRUE(desc_result2.find("transB=OP_N") != std::string::npos);
|
|
ASSERT_TRUE(desc_result2.find("epilogue=EPILOGUE_BIAS") != std::string::npos);
|
|
ASSERT_TRUE(desc_result2.find("biasType=R_16F") != std::string::npos);
|
|
// Should NOT contain epilogue aux info
|
|
ASSERT_TRUE(desc_result2.find("epilogueAuxPointer") == std::string::npos);
|
|
ASSERT_TRUE(desc_result2.front() == '[' && desc_result2.back() == ']');
|
|
|
|
// Test case 3: No bias, with epilogue extension
|
|
desc3.compute_type = rocblaslt_compute_f32;
|
|
desc3.scale_type = HIP_R_32F;
|
|
desc3.op_A = HIPBLAS_OP_N;
|
|
desc3.op_B = HIPBLAS_OP_N;
|
|
desc3.epilogue = ROCBLASLT_EPILOGUE_GELU_AUX;
|
|
desc3.bias = nullptr;
|
|
desc3.bias_type = HIPBLASLT_DATATYPE_INVALID;
|
|
desc3.aux_type = HIP_R_32F;
|
|
desc3.e = reinterpret_cast<void*>(0x87654321);
|
|
desc3.lde = 128;
|
|
|
|
std::string desc_result3 = rocblaslt_matmul_desc_to_string(&desc3);
|
|
ASSERT_TRUE(!desc_result3.empty());
|
|
ASSERT_TRUE(desc_result3.find("computeType=COMPUTE_32F") != std::string::npos);
|
|
ASSERT_TRUE(desc_result3.find("epilogue=EPILOGUE_GELU_AUX") != std::string::npos);
|
|
ASSERT_TRUE(desc_result3.find("epilogueAuxPointer=0x") != std::string::npos);
|
|
ASSERT_TRUE(desc_result3.find("epilogueAuxLd=128") != std::string::npos);
|
|
ASSERT_TRUE(desc_result3.find("epilogueAuxDataType=R_32F") != std::string::npos);
|
|
// Should NOT contain bias type info
|
|
ASSERT_TRUE(desc_result3.find("biasType") == std::string::npos);
|
|
ASSERT_TRUE(desc_result3.front() == '[' && desc_result3.back() == ']');
|
|
|
|
// Test case 4: With bias and epilogue extension (most complex case)
|
|
desc4.compute_type = rocblaslt_compute_f64;
|
|
desc4.scale_type = HIP_R_64F;
|
|
desc4.op_A = HIPBLAS_OP_C;
|
|
desc4.op_B = HIPBLAS_OP_C;
|
|
desc4.epilogue = ROCBLASLT_EPILOGUE_GELU_AUX_BIAS;
|
|
desc4.bias = reinterpret_cast<void*>(0xABCDEF00);
|
|
desc4.bias_type = HIP_R_64F;
|
|
desc4.aux_type = HIP_R_64F;
|
|
desc4.e = reinterpret_cast<void*>(0x11223344);
|
|
desc4.lde = 256;
|
|
|
|
std::string desc_result4 = rocblaslt_matmul_desc_to_string(&desc4);
|
|
ASSERT_TRUE(!desc_result4.empty());
|
|
ASSERT_TRUE(desc_result4.find("computeType=COMPUTE_64F") != std::string::npos);
|
|
ASSERT_TRUE(desc_result4.find("scaleType=R_64F") != std::string::npos);
|
|
ASSERT_TRUE(desc_result4.find("transA=OP_C") != std::string::npos);
|
|
ASSERT_TRUE(desc_result4.find("transB=OP_C") != std::string::npos);
|
|
ASSERT_TRUE(desc_result4.find("epilogue=EPILOGUE_GELU_AUX_BIAS") != std::string::npos);
|
|
ASSERT_TRUE(desc_result4.find("biasType=R_64F") != std::string::npos);
|
|
ASSERT_TRUE(desc_result4.find("epilogueAuxPointer=0x") != std::string::npos);
|
|
ASSERT_TRUE(desc_result4.find("epilogueAuxLd=256") != std::string::npos);
|
|
ASSERT_TRUE(desc_result4.find("epilogueAuxDataType=R_64F") != std::string::npos);
|
|
ASSERT_TRUE(desc_result4.front() == '[' && desc_result4.back() == ']');
|
|
|
|
// Test case 5: Epilogue extension without aux_type
|
|
_rocblaslt_matmul_desc desc5;
|
|
desc5.compute_type = rocblaslt_compute_i32;
|
|
desc5.scale_type = HIP_R_32I;
|
|
desc5.op_A = HIPBLAS_OP_N;
|
|
desc5.op_B = HIPBLAS_OP_N;
|
|
desc5.epilogue = ROCBLASLT_EPILOGUE_DGELU_BGRAD;
|
|
desc5.bias = nullptr;
|
|
desc5.bias_type = HIPBLASLT_DATATYPE_INVALID;
|
|
desc5.aux_type = HIPBLASLT_DATATYPE_INVALID; // Invalid aux type
|
|
desc5.e = reinterpret_cast<void*>(0x55555555);
|
|
desc5.lde = 64;
|
|
|
|
std::string desc_result5 = rocblaslt_matmul_desc_to_string(&desc5);
|
|
ASSERT_TRUE(!desc_result5.empty());
|
|
ASSERT_TRUE(desc_result5.find("computeType=COMPUTE_32I") != std::string::npos);
|
|
ASSERT_TRUE(desc_result5.find("epilogue=EPILOGUE_DGELU_BGRAD") != std::string::npos);
|
|
ASSERT_TRUE(desc_result5.find("epilogueAuxPointer=0x") != std::string::npos);
|
|
ASSERT_TRUE(desc_result5.find("epilogueAuxLd=64") != std::string::npos);
|
|
// Should NOT contain epilogueAuxDataType since aux_type is invalid
|
|
ASSERT_TRUE(desc_result5.find("epilogueAuxDataType") == std::string::npos);
|
|
ASSERT_TRUE(desc_result5.front() == '[' && desc_result5.back() == ']');
|
|
|
|
// Test case 6: Epilogue extension without aux_type
|
|
_rocblaslt_matmul_desc desc6;
|
|
desc6.compute_type = rocblaslt_compute_i32;
|
|
desc6.scale_type = HIP_R_32I;
|
|
desc6.op_A = HIPBLAS_OP_N;
|
|
desc6.op_B = HIPBLAS_OP_N;
|
|
desc6.epilogue = ROCBLASLT_EPILOGUE_DRELU_BGRAD;
|
|
desc6.bias = nullptr;
|
|
desc6.bias_type = HIPBLASLT_DATATYPE_INVALID;
|
|
desc6.aux_type = HIPBLASLT_DATATYPE_INVALID; // Invalid aux type
|
|
desc6.e = reinterpret_cast<void*>(0x55555555);
|
|
desc6.lde = 64;
|
|
|
|
std::string desc_result6 = rocblaslt_matmul_desc_to_string(&desc6);
|
|
ASSERT_TRUE(!desc_result6.empty());
|
|
ASSERT_TRUE(desc_result6.find("computeType=COMPUTE_32I") != std::string::npos);
|
|
ASSERT_TRUE(desc_result6.find("epilogue=EPILOGUE_DRELU_BGRAD") != std::string::npos);
|
|
ASSERT_TRUE(desc_result6.find("epilogueAuxPointer=0x") != std::string::npos);
|
|
ASSERT_TRUE(desc_result6.find("epilogueAuxLd=64") != std::string::npos);
|
|
// Should NOT contain epilogueAuxDataType since aux_type is invalid
|
|
ASSERT_TRUE(desc_result6.find("epilogueAuxDataType") == std::string::npos);
|
|
ASSERT_TRUE(desc_result6.front() == '[' && desc_result6.back() == ']');
|
|
|
|
// Test different data types
|
|
_rocblaslt_matmul_desc desc7;
|
|
desc7.compute_type = rocblaslt_compute_f32_fast_bf16;
|
|
desc7.scale_type = HIP_R_16BF;
|
|
desc7.op_A = HIPBLAS_OP_N;
|
|
desc7.op_B = HIPBLAS_OP_T;
|
|
desc7.epilogue = ROCBLASLT_EPILOGUE_RELU_BIAS;
|
|
desc7.bias = reinterpret_cast<void*>(0x99999999);
|
|
desc7.bias_type = HIP_R_8F_E4M3_FNUZ;
|
|
desc7.aux_type = HIPBLASLT_DATATYPE_INVALID;
|
|
desc7.e = nullptr;
|
|
desc7.lde = 0;
|
|
|
|
std::string desc_result7 = rocblaslt_matmul_desc_to_string(&desc7);
|
|
ASSERT_TRUE(!desc_result7.empty());
|
|
ASSERT_TRUE(desc_result7.find("computeType=COMPUTE_32F_16BF") != std::string::npos);
|
|
ASSERT_TRUE(desc_result7.find("scaleType=R_16BF") != std::string::npos);
|
|
ASSERT_TRUE(desc_result7.find("epilogue=EPILOGUE_RELU_BIAS") != std::string::npos);
|
|
ASSERT_TRUE(desc_result7.find("biasType=R_8F_E4M3_FNUZ") != std::string::npos);
|
|
ASSERT_TRUE(desc_result7.front() == '[' && desc_result7.back() == ']');
|
|
|
|
// Test case 1: No exception (nullptr) - should return success
|
|
rocblaslt_status excep_result1 = exception_to_rocblaslt_status(nullptr);
|
|
ASSERT_TRUE(excep_result1 == rocblaslt_status_success);
|
|
|
|
// Test case 2: Catch rocblaslt_status exception - should return the status value
|
|
std::exception_ptr status_exception;
|
|
try
|
|
{
|
|
throw rocblaslt_status_invalid_handle;
|
|
}
|
|
catch(...)
|
|
{
|
|
status_exception = std::current_exception();
|
|
}
|
|
|
|
rocblaslt_status excep_result2 = exception_to_rocblaslt_status(status_exception);
|
|
ASSERT_TRUE(excep_result2 == rocblaslt_status_invalid_handle);
|
|
|
|
// Test case 3: Different rocblaslt_status values
|
|
std::exception_ptr status_exception2;
|
|
try
|
|
{
|
|
throw rocblaslt_status_not_initialized;
|
|
}
|
|
catch(...)
|
|
{
|
|
status_exception2 = std::current_exception();
|
|
}
|
|
|
|
rocblaslt_status excep_result3 = exception_to_rocblaslt_status(status_exception2);
|
|
ASSERT_TRUE(excep_result3 == rocblaslt_status_not_initialized);
|
|
|
|
// Test case 4: Catch std::bad_alloc - should return memory error
|
|
std::exception_ptr bad_alloc_exception;
|
|
try
|
|
{
|
|
throw std::bad_alloc();
|
|
}
|
|
catch(...)
|
|
{
|
|
bad_alloc_exception = std::current_exception();
|
|
}
|
|
|
|
rocblaslt_status excep_result4 = exception_to_rocblaslt_status(bad_alloc_exception);
|
|
ASSERT_TRUE(excep_result4 == rocblaslt_status_memory_error);
|
|
|
|
// Test all epilogue values that should return true (activation enabled)
|
|
ASSERT_TRUE(is_act_enabled(ROCBLASLT_EPILOGUE_RELU) == true);
|
|
ASSERT_TRUE(is_act_enabled(ROCBLASLT_EPILOGUE_RELU_BIAS) == true);
|
|
ASSERT_TRUE(is_act_enabled(ROCBLASLT_EPILOGUE_GELU) == true);
|
|
ASSERT_TRUE(is_act_enabled(ROCBLASLT_EPILOGUE_GELU_BIAS) == true);
|
|
ASSERT_TRUE(is_act_enabled(ROCBLASLT_EPILOGUE_GELU_AUX) == true);
|
|
ASSERT_TRUE(is_act_enabled(ROCBLASLT_EPILOGUE_GELU_AUX_BIAS) == true);
|
|
ASSERT_TRUE(is_act_enabled(ROCBLASLT_EPILOGUE_DGELU) == true);
|
|
ASSERT_TRUE(is_act_enabled(ROCBLASLT_EPILOGUE_DGELU_BGRAD) == true);
|
|
ASSERT_TRUE(is_act_enabled(ROCBLASLT_EPILOGUE_DRELU) == true);
|
|
ASSERT_TRUE(is_act_enabled(ROCBLASLT_EPILOGUE_DRELU_BGRAD) == true);
|
|
ASSERT_TRUE(is_act_enabled(ROCBLASLT_EPILOGUE_SWISH_EXT) == true);
|
|
ASSERT_TRUE(is_act_enabled(ROCBLASLT_EPILOGUE_SWISH_BIAS_EXT) == true);
|
|
ASSERT_TRUE(is_act_enabled(ROCBLASLT_EPILOGUE_CLAMP_EXT) == true);
|
|
ASSERT_TRUE(is_act_enabled(ROCBLASLT_EPILOGUE_CLAMP_BIAS_EXT) == true);
|
|
// Test all epilogue values that should return false (activation disabled)
|
|
ASSERT_TRUE(is_act_enabled(ROCBLASLT_EPILOGUE_DEFAULT) == false);
|
|
ASSERT_TRUE(is_act_enabled(ROCBLASLT_EPILOGUE_BIAS) == false);
|
|
}
|
|
|
|
inline void testing_aux_status_func(const Arguments& arg)
|
|
{
|
|
// Test get_rocblaslt_status_for_hip_status function
|
|
ASSERT_TRUE(get_rocblaslt_status_for_hip_status(hipSuccess) == rocblaslt_status_success);
|
|
ASSERT_TRUE(get_rocblaslt_status_for_hip_status(hipErrorMemoryAllocation)
|
|
== rocblaslt_status_memory_error);
|
|
ASSERT_TRUE(get_rocblaslt_status_for_hip_status(hipErrorLaunchOutOfResources)
|
|
== rocblaslt_status_memory_error);
|
|
ASSERT_TRUE(get_rocblaslt_status_for_hip_status(hipErrorInvalidDevicePointer)
|
|
== rocblaslt_status_invalid_pointer);
|
|
ASSERT_TRUE(get_rocblaslt_status_for_hip_status(hipErrorInvalidDevice)
|
|
== rocblaslt_status_invalid_handle);
|
|
ASSERT_TRUE(get_rocblaslt_status_for_hip_status(hipErrorInvalidResourceHandle)
|
|
== rocblaslt_status_invalid_handle);
|
|
ASSERT_TRUE(get_rocblaslt_status_for_hip_status(hipErrorInvalidValue)
|
|
== rocblaslt_status_internal_error);
|
|
ASSERT_TRUE(get_rocblaslt_status_for_hip_status(hipErrorNoDevice)
|
|
== rocblaslt_status_internal_error);
|
|
ASSERT_TRUE(get_rocblaslt_status_for_hip_status(hipErrorUnknown)
|
|
== rocblaslt_status_internal_error);
|
|
|
|
// Test default case with unknown/unmapped hip errors -> rocblaslt_status_internal_error
|
|
ASSERT_TRUE(get_rocblaslt_status_for_hip_status(static_cast<hipError_t>(999))
|
|
== rocblaslt_status_internal_error);
|
|
}
|
|
|
|
inline void testing_aux_hipblaslt_func(const Arguments& arg)
|
|
{
|
|
// Test RocBlasLtStatusToHIPStatus
|
|
ASSERT_TRUE(RocBlasLtStatusToHIPStatus(rocblaslt_status_success) == HIPBLAS_STATUS_SUCCESS);
|
|
ASSERT_TRUE(RocBlasLtStatusToHIPStatus(rocblaslt_status_invalid_handle)
|
|
== HIPBLAS_STATUS_NOT_INITIALIZED);
|
|
ASSERT_TRUE(RocBlasLtStatusToHIPStatus(rocblaslt_status_not_implemented)
|
|
== HIPBLAS_STATUS_INTERNAL_ERROR);
|
|
ASSERT_TRUE(RocBlasLtStatusToHIPStatus(rocblaslt_status_invalid_pointer)
|
|
== HIPBLAS_STATUS_INVALID_VALUE);
|
|
ASSERT_TRUE(RocBlasLtStatusToHIPStatus(rocblaslt_status_invalid_size)
|
|
== HIPBLAS_STATUS_INVALID_VALUE);
|
|
ASSERT_TRUE(RocBlasLtStatusToHIPStatus(rocblaslt_status_memory_error)
|
|
== HIPBLAS_STATUS_ALLOC_FAILED);
|
|
ASSERT_TRUE(RocBlasLtStatusToHIPStatus(rocblaslt_status_internal_error)
|
|
== HIPBLAS_STATUS_INTERNAL_ERROR);
|
|
ASSERT_TRUE(RocBlasLtStatusToHIPStatus(rocblaslt_status_invalid_value)
|
|
== HIPBLAS_STATUS_INVALID_VALUE);
|
|
ASSERT_TRUE(RocBlasLtStatusToHIPStatus(rocblaslt_status_arch_mismatch)
|
|
== HIPBLAS_STATUS_ARCH_MISMATCH);
|
|
|
|
// Test default case - should throw HIPBLAS_STATUS_INVALID_ENUM
|
|
bool exception_thrown = false;
|
|
hipblasStatus_t thrown_status = HIPBLAS_STATUS_SUCCESS;
|
|
|
|
try
|
|
{
|
|
RocBlasLtStatusToHIPStatus(static_cast<rocblaslt_status_>(999));
|
|
}
|
|
catch(hipblasStatus_t status)
|
|
{
|
|
exception_thrown = true;
|
|
thrown_status = status;
|
|
}
|
|
catch(...)
|
|
{
|
|
exception_thrown = true;
|
|
thrown_status = HIPBLAS_STATUS_INTERNAL_ERROR; // Unexpected exception type
|
|
}
|
|
|
|
ASSERT_TRUE(exception_thrown);
|
|
ASSERT_TRUE(thrown_status == HIPBLAS_STATUS_INVALID_ENUM);
|
|
|
|
// Test hipblasLtMatrixTransformDescSetAttribute function
|
|
hipblasLtMatrixTransformDesc_t transformDesc;
|
|
CHECK_HIPBLASLT_ERROR(hipblasLtMatrixTransformDescCreate(&transformDesc, HIP_R_32F));
|
|
|
|
// Test SCALE_TYPE attribute
|
|
hipDataType scaleDatatype{HIP_R_16F};
|
|
ASSERT_TRUE(hipblasLtMatrixTransformDescSetAttribute(transformDesc,
|
|
HIPBLASLT_MATRIX_TRANSFORM_DESC_SCALE_TYPE,
|
|
&scaleDatatype,
|
|
sizeof(scaleDatatype))
|
|
== HIPBLAS_STATUS_SUCCESS);
|
|
|
|
// Test POINTER_MODE attribute
|
|
hipblasLtPointerMode_t pointerMode{HIPBLASLT_POINTER_MODE_DEVICE};
|
|
ASSERT_TRUE(
|
|
hipblasLtMatrixTransformDescSetAttribute(transformDesc,
|
|
HIPBLASLT_MATRIX_TRANSFORM_DESC_POINTER_MODE,
|
|
&pointerMode,
|
|
sizeof(pointerMode))
|
|
== HIPBLAS_STATUS_SUCCESS);
|
|
|
|
// Test TRANSA attribute
|
|
hipblasOperation_t transA{HIPBLAS_OP_T};
|
|
ASSERT_TRUE(hipblasLtMatrixTransformDescSetAttribute(
|
|
transformDesc, HIPBLASLT_MATRIX_TRANSFORM_DESC_TRANSA, &transA, sizeof(transA))
|
|
== HIPBLAS_STATUS_SUCCESS);
|
|
|
|
// Test TRANSB attribute
|
|
hipblasOperation_t transB{HIPBLAS_OP_C};
|
|
ASSERT_TRUE(hipblasLtMatrixTransformDescSetAttribute(
|
|
transformDesc, HIPBLASLT_MATRIX_TRANSFORM_DESC_TRANSB, &transB, sizeof(transB))
|
|
== HIPBLAS_STATUS_SUCCESS);
|
|
|
|
// Test invalid buffer (nullptr)
|
|
ASSERT_TRUE(
|
|
hipblasLtMatrixTransformDescSetAttribute(
|
|
transformDesc, HIPBLASLT_MATRIX_TRANSFORM_DESC_SCALE_TYPE, nullptr, sizeof(hipDataType))
|
|
== HIPBLAS_STATUS_INVALID_VALUE);
|
|
|
|
// Test invalid size
|
|
ASSERT_TRUE(hipblasLtMatrixTransformDescSetAttribute(transformDesc,
|
|
HIPBLASLT_MATRIX_TRANSFORM_DESC_SCALE_TYPE,
|
|
&scaleDatatype,
|
|
sizeof(int16_t))
|
|
== HIPBLAS_STATUS_INVALID_VALUE);
|
|
|
|
// Test SCALE_TYPE attribute get
|
|
int32_t retrievedScaleType;
|
|
size_t sizeWritten;
|
|
ASSERT_TRUE(hipblasLtMatrixTransformDescGetAttribute(transformDesc,
|
|
HIPBLASLT_MATRIX_TRANSFORM_DESC_SCALE_TYPE,
|
|
&retrievedScaleType,
|
|
sizeof(retrievedScaleType),
|
|
&sizeWritten)
|
|
== HIPBLAS_STATUS_SUCCESS);
|
|
ASSERT_TRUE(static_cast<hipDataType>(retrievedScaleType) == HIP_R_16F);
|
|
ASSERT_TRUE(sizeWritten == sizeof(int32_t));
|
|
|
|
// Test POINTER_MODE attribute get
|
|
int32_t retrievedPointerMode;
|
|
ASSERT_TRUE(
|
|
hipblasLtMatrixTransformDescGetAttribute(transformDesc,
|
|
HIPBLASLT_MATRIX_TRANSFORM_DESC_POINTER_MODE,
|
|
&retrievedPointerMode,
|
|
sizeof(retrievedPointerMode),
|
|
&sizeWritten)
|
|
== HIPBLAS_STATUS_SUCCESS);
|
|
ASSERT_TRUE(static_cast<hipblasLtPointerMode_t>(retrievedPointerMode)
|
|
== HIPBLASLT_POINTER_MODE_DEVICE);
|
|
ASSERT_TRUE(sizeWritten == sizeof(int32_t));
|
|
|
|
// Test TRANSA attribute get
|
|
int32_t retrievedTransA;
|
|
ASSERT_TRUE(hipblasLtMatrixTransformDescGetAttribute(transformDesc,
|
|
HIPBLASLT_MATRIX_TRANSFORM_DESC_TRANSA,
|
|
&retrievedTransA,
|
|
sizeof(retrievedTransA),
|
|
&sizeWritten)
|
|
== HIPBLAS_STATUS_SUCCESS);
|
|
ASSERT_TRUE(static_cast<hipblasOperation_t>(retrievedTransA) == HIPBLAS_OP_T);
|
|
ASSERT_TRUE(sizeWritten == sizeof(int32_t));
|
|
|
|
// Test TRANSB attribute get
|
|
int32_t retrievedTransB;
|
|
ASSERT_TRUE(hipblasLtMatrixTransformDescGetAttribute(transformDesc,
|
|
HIPBLASLT_MATRIX_TRANSFORM_DESC_TRANSB,
|
|
&retrievedTransB,
|
|
sizeof(retrievedTransB),
|
|
&sizeWritten)
|
|
== HIPBLAS_STATUS_SUCCESS);
|
|
ASSERT_TRUE(static_cast<hipblasOperation_t>(retrievedTransB) == HIPBLAS_OP_C);
|
|
ASSERT_TRUE(sizeWritten == sizeof(int32_t));
|
|
|
|
// Test error cases: both sizeInBytes and sizeWritten are 0/nullptr
|
|
ASSERT_TRUE(hipblasLtMatrixTransformDescGetAttribute(transformDesc,
|
|
HIPBLASLT_MATRIX_TRANSFORM_DESC_SCALE_TYPE,
|
|
&retrievedScaleType,
|
|
0,
|
|
nullptr)
|
|
== HIPBLAS_STATUS_INVALID_VALUE);
|
|
|
|
// Test error case: sizeInBytes provided but sizeWritten is nullptr
|
|
ASSERT_TRUE(hipblasLtMatrixTransformDescGetAttribute(transformDesc,
|
|
HIPBLASLT_MATRIX_TRANSFORM_DESC_SCALE_TYPE,
|
|
&retrievedScaleType,
|
|
sizeof(retrievedScaleType),
|
|
nullptr)
|
|
== HIPBLAS_STATUS_INVALID_VALUE);
|
|
|
|
// Test error case: invalid size (not sizeof(int32_t))
|
|
ASSERT_TRUE(hipblasLtMatrixTransformDescGetAttribute(transformDesc,
|
|
HIPBLASLT_MATRIX_TRANSFORM_DESC_SCALE_TYPE,
|
|
&retrievedScaleType,
|
|
sizeof(int16_t),
|
|
&sizeWritten)
|
|
== HIPBLAS_STATUS_INVALID_VALUE);
|
|
|
|
// Test error case: invalid attribute (using default case)
|
|
ASSERT_TRUE(hipblasLtMatrixTransformDescGetAttribute(
|
|
transformDesc,
|
|
static_cast<hipblasLtMatrixTransformDescAttributes_t>(999),
|
|
&retrievedScaleType,
|
|
sizeof(retrievedScaleType),
|
|
&sizeWritten)
|
|
== HIPBLAS_STATUS_INVALID_VALUE);
|
|
|
|
CHECK_HIPBLASLT_ERROR(hipblasLtMatrixTransformDescDestroy(transformDesc));
|
|
}
|
|
|
|
inline void testing_aux_tensile_host_func(const Arguments& arg)
|
|
{
|
|
// Test hipDataType_to_tensile_type function
|
|
ASSERT_TRUE(hipDataType_to_tensile_type(HIP_R_16F) == rocisa::DataType::Half);
|
|
ASSERT_TRUE(hipDataType_to_tensile_type(HIP_R_32F) == rocisa::DataType::Float);
|
|
ASSERT_TRUE(hipDataType_to_tensile_type(HIP_R_64F) == rocisa::DataType::Double);
|
|
ASSERT_TRUE(hipDataType_to_tensile_type(HIP_R_16BF) == rocisa::DataType::BFloat16);
|
|
ASSERT_TRUE(hipDataType_to_tensile_type(HIP_R_8F_E4M3_FNUZ) == rocisa::DataType::Float8_fnuz);
|
|
ASSERT_TRUE(hipDataType_to_tensile_type(HIP_R_8F_E5M2_FNUZ) == rocisa::DataType::BFloat8_fnuz);
|
|
ASSERT_TRUE(hipDataType_to_tensile_type(HIP_R_8F_E4M3) == rocisa::DataType::Float8);
|
|
ASSERT_TRUE(hipDataType_to_tensile_type(HIP_R_8F_E5M2) == rocisa::DataType::BFloat8);
|
|
ASSERT_TRUE(hipDataType_to_tensile_type(HIP_R_8I) == rocisa::DataType::Int8);
|
|
ASSERT_TRUE(hipDataType_to_tensile_type(HIP_R_32I) == rocisa::DataType::Int32);
|
|
|
|
// Test rocComputeType_to_tensile_type function
|
|
ASSERT_TRUE(rocComputeType_to_tensile_type(rocblaslt_compute_f32_fast_xf32)
|
|
== rocisa::DataType::XFloat32);
|
|
ASSERT_TRUE(rocComputeType_to_tensile_type(rocblaslt_compute_f32_fast_f16)
|
|
== rocisa::DataType::Float);
|
|
ASSERT_TRUE(rocComputeType_to_tensile_type(rocblaslt_compute_f32_fast_bf16)
|
|
== rocisa::DataType::Float);
|
|
ASSERT_TRUE(rocComputeType_to_tensile_type(rocblaslt_compute_f16) == rocisa::DataType::Float);
|
|
ASSERT_TRUE(rocComputeType_to_tensile_type(rocblaslt_compute_f32) == rocisa::DataType::Float);
|
|
ASSERT_TRUE(rocComputeType_to_tensile_type(rocblaslt_compute_f32_fast_f8_fnuz)
|
|
== rocisa::DataType::Float);
|
|
ASSERT_TRUE(rocComputeType_to_tensile_type(rocblaslt_compute_f32_fast_bf8_fnuz)
|
|
== rocisa::DataType::Float);
|
|
ASSERT_TRUE(rocComputeType_to_tensile_type(rocblaslt_compute_f32_fast_f8bf8_fnuz)
|
|
== rocisa::DataType::Float);
|
|
ASSERT_TRUE(rocComputeType_to_tensile_type(rocblaslt_compute_f32_fast_bf8f8_fnuz)
|
|
== rocisa::DataType::Float);
|
|
ASSERT_TRUE(rocComputeType_to_tensile_type(rocblaslt_compute_f32_fast_f8)
|
|
== rocisa::DataType::Float);
|
|
ASSERT_TRUE(rocComputeType_to_tensile_type(rocblaslt_compute_f32_fast_bf8)
|
|
== rocisa::DataType::Float);
|
|
ASSERT_TRUE(rocComputeType_to_tensile_type(rocblaslt_compute_f32_fast_f8bf8)
|
|
== rocisa::DataType::Float);
|
|
ASSERT_TRUE(rocComputeType_to_tensile_type(rocblaslt_compute_f32_fast_bf8f8)
|
|
== rocisa::DataType::Float);
|
|
ASSERT_TRUE(rocComputeType_to_tensile_type(rocblaslt_compute_f64) == rocisa::DataType::Double);
|
|
ASSERT_TRUE(rocComputeType_to_tensile_type(rocblaslt_compute_i32) == rocisa::DataType::Int32);
|
|
}
|
|
|
|
inline void testing_aux_tuple_helper_equal_func(const Arguments& arg)
|
|
{
|
|
// Test tuple_helper equal functionality
|
|
|
|
// Test basic integer equality
|
|
auto tuple1 = std::make_tuple("key1", 42, "key2", 100);
|
|
auto tuple2 = std::make_tuple("key1", 42, "key2", 100);
|
|
auto tuple3 = std::make_tuple("key1", 42, "key2", 99);
|
|
|
|
tuple_helper::equal_t<decltype(tuple1)> equal_checker;
|
|
|
|
// Test equal tuples
|
|
ASSERT_TRUE(equal_checker(tuple1, tuple2));
|
|
|
|
// Test unequal tuples (different values)
|
|
ASSERT_FALSE(equal_checker(tuple1, tuple3));
|
|
|
|
// Test C-string equality
|
|
auto str_tuple1 = std::make_tuple("name", "test", "value", "data");
|
|
auto str_tuple2 = std::make_tuple("name", "test", "value", "data");
|
|
auto str_tuple3 = std::make_tuple("name", "test", "value", "different");
|
|
|
|
tuple_helper::equal_t<decltype(str_tuple1)> str_equal_checker;
|
|
|
|
// Test equal C-string tuples
|
|
ASSERT_TRUE(str_equal_checker(str_tuple1, str_tuple2));
|
|
|
|
// Test unequal C-string tuples
|
|
ASSERT_FALSE(str_equal_checker(str_tuple1, str_tuple3));
|
|
}
|
|
|
|
#ifdef HIPBLASLT_USE_ROCROLLER
|
|
inline void testing_aux_rocblaslt_rocroller_host_func(const Arguments& arg)
|
|
{
|
|
hipblasLtHandle_t handle;
|
|
CHECK_HIPBLASLT_ERROR(hipblasLtCreate(&handle));
|
|
|
|
hipblasLtMatmulDesc_t matmul;
|
|
CHECK_HIPBLASLT_ERROR(hipblasLtMatmulDescCreate(&matmul, arg.compute_type, arg.scale_type));
|
|
|
|
hipblasOperation_t opA = HIPBLAS_OP_T;
|
|
hipblasOperation_t opB = HIPBLAS_OP_N;
|
|
int64_t m = 1;
|
|
int64_t n = 1;
|
|
int64_t k = 1;
|
|
float alpha_v = arg.alpha;
|
|
void* alpha = &alpha_v;
|
|
float beta_v = arg.beta;
|
|
void* beta = &beta_v;
|
|
int64_t lda = 1;
|
|
int64_t ldb = 1;
|
|
int64_t ldc = 1;
|
|
int64_t ldd = 1;
|
|
int64_t lde = 1;
|
|
|
|
hipStream_t stream;
|
|
CHECK_HIP_ERROR(hipStreamCreate(&stream));
|
|
hipblasLtMatrixLayout_t matA, matB, matC, matD;
|
|
CHECK_HIPBLASLT_ERROR(hipblasLtMatrixLayoutCreate(&matA, arg.a_type, m, k, m));
|
|
CHECK_HIPBLASLT_ERROR(hipblasLtMatrixLayoutCreate(&matB, arg.a_type, k, n, k));
|
|
CHECK_HIPBLASLT_ERROR(hipblasLtMatrixLayoutCreate(&matC, arg.a_type, m, n, m));
|
|
CHECK_HIPBLASLT_ERROR(hipblasLtMatrixLayoutCreate(&matD, arg.a_type, m, n, m));
|
|
hipDataType a_type, b_type, c_type, d_type;
|
|
|
|
const int request_solutions = 1;
|
|
hipblasLtMatmulHeuristicResult_t heuristicResult[request_solutions];
|
|
int returnedAlgoCount = 0;
|
|
size_t max_workspace_size = 128 * 1024 * 1024;
|
|
hipblasLtMatmulPreference_t pref;
|
|
CHECK_HIPBLASLT_ERROR(hipblasLtMatmulPreferenceCreate(&pref));
|
|
CHECK_HIPBLASLT_ERROR(
|
|
hipblasLtMatmulPreferenceSetAttribute(pref,
|
|
HIPBLASLT_MATMUL_PREF_MAX_WORKSPACE_BYTES,
|
|
&max_workspace_size,
|
|
sizeof(max_workspace_size)));
|
|
|
|
void* d_workspace;
|
|
if(max_workspace_size > 0)
|
|
CHECK_HIP_ERROR(hipMalloc(&d_workspace, max_workspace_size));
|
|
|
|
CHECK_HIPBLASLT_ERROR(hipblasLtMatmulAlgoGetHeuristic(handle,
|
|
matmul,
|
|
matA,
|
|
matB,
|
|
matC,
|
|
matD,
|
|
pref,
|
|
request_solutions,
|
|
heuristicResult,
|
|
&returnedAlgoCount));
|
|
|
|
CHECK_SOLUTION_FOUND(returnedAlgoCount);
|
|
rocblaslt_matmul_desc matmul_descr = (rocblaslt_matmul_desc)matmul;
|
|
int64_t batch_count = 1;
|
|
void * A, *B, *C, *D, *E, *d_alphaVec; // device
|
|
CHECK_HIP_ERROR(hipMalloc(&A, m * k * batch_count * sizeof(int64_t)));
|
|
CHECK_HIP_ERROR(hipMalloc(&B, n * k * batch_count * sizeof(int64_t)));
|
|
CHECK_HIP_ERROR(hipMalloc(&C, m * n * batch_count * sizeof(int64_t)));
|
|
CHECK_HIP_ERROR(hipMalloc(&D, m * n * batch_count * sizeof(int64_t)));
|
|
CHECK_HIP_ERROR(hipMalloc(&E, m * n * batch_count * sizeof(int64_t)));
|
|
|
|
int64_t batch_stride_a = 0;
|
|
int64_t batch_stride_b = 0;
|
|
int64_t batch_stride_c = 0;
|
|
int64_t batch_stride_d = 0;
|
|
int64_t batch_stride_e = 0;
|
|
bool strided_batch = true;
|
|
bool grouped_gemm = true;
|
|
void* bias = nullptr;
|
|
hipDataType bias_type;
|
|
void* scaleAlphaVec = nullptr;
|
|
hipDataType aux_type;
|
|
bool gradient = false;
|
|
rocblaslt_compute_type compute_type;
|
|
rocblaslt_handle roc_handle = (rocblaslt_handle)handle;
|
|
hipblasLtBatchMode_t batchMode = HIPBLASLT_BATCH_MODE_STRIDED;
|
|
rocblaslt_status isValid = rocblaslt_matmul_valid_args(matmul_descr,
|
|
A,
|
|
B,
|
|
C,
|
|
D,
|
|
(rocblaslt_matrix_layout)matA,
|
|
(rocblaslt_matrix_layout)matB,
|
|
(rocblaslt_matrix_layout)matC,
|
|
(rocblaslt_matrix_layout)matD,
|
|
alpha,
|
|
beta,
|
|
m,
|
|
n,
|
|
k,
|
|
a_type,
|
|
lda,
|
|
batch_stride_a,
|
|
b_type,
|
|
ldb,
|
|
batch_stride_b,
|
|
c_type,
|
|
ldc,
|
|
batch_stride_c,
|
|
d_type,
|
|
ldd,
|
|
batch_stride_d,
|
|
lde,
|
|
batch_stride_e,
|
|
bias,
|
|
bias_type,
|
|
scaleAlphaVec,
|
|
E,
|
|
aux_type,
|
|
gradient,
|
|
compute_type,
|
|
false,
|
|
false);
|
|
|
|
ASSERT_TRUE(isValid == rocblaslt_status_continue);
|
|
|
|
RocblasltContractionProblem problem{opA,
|
|
opB,
|
|
m,
|
|
n,
|
|
k,
|
|
alpha,
|
|
a_type,
|
|
A, // A
|
|
nullptr,
|
|
lda, // arg.lda
|
|
batch_stride_a,
|
|
b_type,
|
|
B, // B
|
|
nullptr,
|
|
ldb, // arg.ldb
|
|
batch_stride_b,
|
|
beta,
|
|
c_type,
|
|
C, // C
|
|
nullptr,
|
|
ldc, // arg.ldc
|
|
batch_stride_c,
|
|
d_type,
|
|
D, // D
|
|
nullptr,
|
|
ldd, // arg.ldc
|
|
batch_stride_d,
|
|
E, // E
|
|
nullptr,
|
|
lde, //arg.lde
|
|
batch_stride_e,
|
|
batch_count,
|
|
strided_batch,
|
|
grouped_gemm,
|
|
gradient,
|
|
matmul_descr->compute_type,
|
|
HIPBLASLT_DATATYPE_INVALID,
|
|
bias,
|
|
matmul_descr->scaleA,
|
|
matmul_descr->scaleB,
|
|
matmul_descr->scaleC,
|
|
matmul_descr->scaleD,
|
|
matmul_descr->scaleE,
|
|
scaleAlphaVec,
|
|
matmul_descr->scaleAType,
|
|
matmul_descr->scaleBType,
|
|
arg.bias_type,
|
|
arg.aux_type,
|
|
matmul_descr->epilogue,
|
|
matmul_descr->amaxD,
|
|
nullptr,
|
|
max_workspace_size, // workspaceSize
|
|
HIPBLASLT_MATMUL_DESC_EPILOGUE_ACT_ARG0_EXT, // act0
|
|
HIPBLASLT_MATMUL_DESC_EPILOGUE_ACT_ARG1_EXT, // act1
|
|
stream, // stream
|
|
roc_handle->Synchronizer,
|
|
arg.swizzle_a, // swizzleA
|
|
arg.swizzle_b, // swizzleB
|
|
batchMode,
|
|
0}; // bias_stride
|
|
|
|
const hipblasLtMatmulAlgo_t* hip_algo = &heuristicResult[0].algo;
|
|
const rocblaslt_matmul_algo* roc_algo = (const rocblaslt_matmul_algo*)hip_algo;
|
|
|
|
ASSERT_TRUE(runRocRollerContractionProblem(roc_handle, nullptr, problem)
|
|
!= rocblaslt_status_success);
|
|
ASSERT_TRUE(runRocRollerContractionProblem(roc_handle, roc_algo, problem)
|
|
!= rocblaslt_status_success);
|
|
|
|
hipblasLtMatmulAlgo_t* hip_algo2 = &heuristicResult[0].algo;
|
|
rocblaslt_matmul_algo* roc_algo2 = (rocblaslt_matmul_algo*)hip_algo;
|
|
ASSERT_TRUE(isRocRollerSolutionSupported(roc_handle, problem, roc_algo2, &max_workspace_size)
|
|
!= rocblaslt_status_success);
|
|
|
|
// Free GPU memory allocations
|
|
CHECK_HIP_ERROR(hipFree(A));
|
|
CHECK_HIP_ERROR(hipFree(B));
|
|
CHECK_HIP_ERROR(hipFree(C));
|
|
CHECK_HIP_ERROR(hipFree(D));
|
|
CHECK_HIP_ERROR(hipFree(E));
|
|
|
|
// Free workspace
|
|
CHECK_HIP_ERROR(hipFree(d_workspace));
|
|
|
|
// Destroy preference object
|
|
CHECK_HIPBLASLT_ERROR(hipblasLtMatmulPreferenceDestroy(pref));
|
|
|
|
// Destroy handles
|
|
CHECK_HIPBLASLT_ERROR(hipblasLtMatmulDescDestroy(matmul));
|
|
CHECK_HIPBLASLT_ERROR(hipblasLtMatrixLayoutDestroy(matA));
|
|
CHECK_HIPBLASLT_ERROR(hipblasLtMatrixLayoutDestroy(matB));
|
|
CHECK_HIPBLASLT_ERROR(hipblasLtMatrixLayoutDestroy(matC));
|
|
CHECK_HIPBLASLT_ERROR(hipblasLtMatrixLayoutDestroy(matD));
|
|
CHECK_HIPBLASLT_ERROR(hipblasLtDestroy(handle));
|
|
CHECK_HIP_ERROR(hipStreamDestroy(stream));
|
|
}
|
|
#endif // HIPBLASLT_USE_ROCROLLER
|
|
|
|
// Coverage for the post-GEMM HIPBLASLT_CHECK_NUMERICS scanner: env-var parsing,
|
|
// public drain API, and the happy-path NaN detection round-trip.
|
|
inline void testing_aux_check_numerics_func(const Arguments& arg)
|
|
{
|
|
// setenv/unsetenv are not thread-safe; serialize the body so concurrent
|
|
// RUN_TEST_ON_THREADS_STREAMS threads can't interleave env mutations with
|
|
// hipblasLtCreate() reads of those vars.
|
|
static std::mutex env_mutex;
|
|
std::lock_guard<std::mutex> env_lock(env_mutex);
|
|
|
|
auto reset_env = []() {
|
|
unsetenv("HIPBLASLT_CHECK_NUMERICS");
|
|
unsetenv("HIPBLASLT_CHECK_NUMERICS_SCAN_EVERY");
|
|
unsetenv("HIPBLASLT_CHECK_NUMERICS_SCAN_FROM");
|
|
unsetenv("HIPBLASLT_CHECK_NUMERICS_SCAN_UNTIL");
|
|
};
|
|
auto with_env = [](std::initializer_list<std::pair<const char*, const char*>> env,
|
|
auto inspect) {
|
|
for(auto& kv : env)
|
|
setenv(kv.first, kv.second, 1);
|
|
hipblasLtHandle_t h = nullptr;
|
|
EXPECT_HIPBLAS_STATUS(hipblasLtCreate(&h), HIPBLAS_STATUS_SUCCESS);
|
|
inspect((rocblaslt_handle)h);
|
|
EXPECT_HIPBLAS_STATUS(hipblasLtDestroy(h), HIPBLAS_STATUS_SUCCESS);
|
|
};
|
|
|
|
reset_env();
|
|
|
|
EXPECT_HIPBLAS_STATUS(hipblasLtCheckNumericsDrain(nullptr, nullptr),
|
|
HIPBLAS_STATUS_NOT_INITIALIZED);
|
|
|
|
// Default handle (env unset): scanning disabled, drain returns 0.
|
|
{
|
|
hipblasLtHandle_t h = nullptr;
|
|
EXPECT_HIPBLAS_STATUS(hipblasLtCreate(&h), HIPBLAS_STATUS_SUCCESS);
|
|
rocblaslt_handle rh = (rocblaslt_handle)h;
|
|
ASSERT_TRUE(rh->check_numerics == hipblaslt_check_numerics_mode_no_check);
|
|
ASSERT_TRUE(rh->check_numerics_flag == nullptr);
|
|
uint32_t out = 99;
|
|
EXPECT_HIPBLAS_STATUS(hipblasLtCheckNumericsDrain(h, &out), HIPBLAS_STATUS_SUCCESS);
|
|
ASSERT_EQ(out, 0u);
|
|
EXPECT_HIPBLAS_STATUS(hipblasLtCheckNumericsDrain(h, nullptr), HIPBLAS_STATUS_SUCCESS);
|
|
EXPECT_HIPBLAS_STATUS(hipblasLtDestroy(h), HIPBLAS_STATUS_SUCCESS);
|
|
}
|
|
|
|
// HIPBLASLT_CHECK_NUMERICS string/numeric forms.
|
|
auto check_mode = [&](const char* val, hipblaslt_check_numerics_mode expected) {
|
|
reset_env();
|
|
setenv("HIPBLASLT_CHECK_NUMERICS", val, 1);
|
|
hipblasLtHandle_t h = nullptr;
|
|
EXPECT_HIPBLAS_STATUS(hipblasLtCreate(&h), HIPBLAS_STATUS_SUCCESS);
|
|
ASSERT_TRUE(((rocblaslt_handle)h)->check_numerics == expected);
|
|
EXPECT_HIPBLAS_STATUS(hipblasLtDestroy(h), HIPBLAS_STATUS_SUCCESS);
|
|
};
|
|
for(const char* v : {"0", "none", "off", "OFF", "", " ", "garbage", "4", "8"})
|
|
check_mode(v, hipblaslt_check_numerics_mode_no_check);
|
|
for(const char* v : {"1", "info", "INFO"})
|
|
check_mode(v, hipblaslt_check_numerics_mode_info);
|
|
for(const char* v : {"2", "Warn", " warn "})
|
|
check_mode(v, hipblaslt_check_numerics_mode_warn);
|
|
|
|
// SCAN_EVERY parsing: valid values, plus 0/negative/garbage -> 1.
|
|
reset_env();
|
|
with_env({{"HIPBLASLT_CHECK_NUMERICS", "1"}, {"HIPBLASLT_CHECK_NUMERICS_SCAN_EVERY", "5"}},
|
|
[](rocblaslt_handle rh) { ASSERT_EQ(rh->check_numerics_scan_every, 5u); });
|
|
for(const char* v : {"0", "-3", "abc"})
|
|
{
|
|
reset_env();
|
|
with_env({{"HIPBLASLT_CHECK_NUMERICS", "1"}, {"HIPBLASLT_CHECK_NUMERICS_SCAN_EVERY", v}},
|
|
[](rocblaslt_handle rh) { ASSERT_EQ(rh->check_numerics_scan_every, 1u); });
|
|
}
|
|
|
|
// SCAN_FROM / SCAN_UNTIL: valid window, inverted resets to defaults.
|
|
reset_env();
|
|
with_env({{"HIPBLASLT_CHECK_NUMERICS", "2"},
|
|
{"HIPBLASLT_CHECK_NUMERICS_SCAN_FROM", "10"},
|
|
{"HIPBLASLT_CHECK_NUMERICS_SCAN_UNTIL", "20"}},
|
|
[](rocblaslt_handle rh) {
|
|
ASSERT_EQ(rh->check_numerics_scan_from, 10u);
|
|
ASSERT_EQ(rh->check_numerics_scan_until, 20u);
|
|
});
|
|
reset_env();
|
|
with_env({{"HIPBLASLT_CHECK_NUMERICS", "2"},
|
|
{"HIPBLASLT_CHECK_NUMERICS_SCAN_FROM", "600"},
|
|
{"HIPBLASLT_CHECK_NUMERICS_SCAN_UNTIL", "500"}},
|
|
[](rocblaslt_handle rh) {
|
|
ASSERT_EQ(rh->check_numerics_scan_from, 1u);
|
|
ASSERT_EQ(rh->check_numerics_scan_until, ~uint32_t(0));
|
|
});
|
|
|
|
// Happy path: enable scanning, write NaN, scan_D, drain returns call_id 1.
|
|
reset_env();
|
|
setenv("HIPBLASLT_CHECK_NUMERICS", "1", 1);
|
|
{
|
|
hipblasLtHandle_t h = nullptr;
|
|
EXPECT_HIPBLAS_STATUS(hipblasLtCreate(&h), HIPBLAS_STATUS_SUCCESS);
|
|
rocblaslt_handle rh = (rocblaslt_handle)h;
|
|
ASSERT_TRUE(rh->check_numerics_flag != nullptr);
|
|
|
|
constexpr int64_t M = 4, N = 4;
|
|
float* d_buf = nullptr;
|
|
ASSERT_EQ(hipMalloc(&d_buf, M * N * sizeof(float)), hipSuccess);
|
|
std::vector<float> h_buf(M * N, std::numeric_limits<float>::quiet_NaN());
|
|
ASSERT_EQ(hipMemcpy(d_buf, h_buf.data(),
|
|
M * N * sizeof(float), hipMemcpyHostToDevice),
|
|
hipSuccess);
|
|
|
|
const uint32_t call_id = hipblaslt_check_numerics_begin_call(rh);
|
|
ASSERT_EQ(call_id, 1u);
|
|
ASSERT_TRUE(hipblaslt_check_numerics_scan_D(rh, nullptr, call_id,
|
|
M, N, 1, HIP_R_32F,
|
|
d_buf, M, M * N, false)
|
|
== rocblaslt_status_success);
|
|
|
|
uint32_t out = 0;
|
|
EXPECT_HIPBLAS_STATUS(hipblasLtCheckNumericsDrain(h, &out), HIPBLAS_STATUS_SUCCESS);
|
|
ASSERT_EQ(out, 1u);
|
|
// Second drain after reset: no NaN.
|
|
out = 99;
|
|
EXPECT_HIPBLAS_STATUS(hipblasLtCheckNumericsDrain(h, &out), HIPBLAS_STATUS_SUCCESS);
|
|
ASSERT_EQ(out, 0u);
|
|
|
|
ASSERT_EQ(hipFree(d_buf), hipSuccess);
|
|
EXPECT_HIPBLAS_STATUS(hipblasLtDestroy(h), HIPBLAS_STATUS_SUCCESS);
|
|
}
|
|
|
|
// Per-dtype dispatch coverage: every arm of the type switch in
|
|
// hipblaslt_check_numerics_output_D gets a 4x4 NaN-prefilled buffer and
|
|
// we assert the device flag captures call_id 1. Catches a regression in
|
|
// any single dtype's template instantiation that the f32 happy path
|
|
// above would miss.
|
|
auto scan_one_with_nan
|
|
= [&reset_env](hipDataType dt, const void* host_buf, size_t elem_size, uint32_t expected_drain) {
|
|
reset_env();
|
|
setenv("HIPBLASLT_CHECK_NUMERICS", "1", 1);
|
|
hipblasLtHandle_t h = nullptr;
|
|
EXPECT_HIPBLAS_STATUS(hipblasLtCreate(&h), HIPBLAS_STATUS_SUCCESS);
|
|
rocblaslt_handle rh = (rocblaslt_handle)h;
|
|
constexpr int64_t M = 4, N = 4;
|
|
void* d_buf = nullptr;
|
|
ASSERT_EQ(hipMalloc(&d_buf, M * N * elem_size), hipSuccess);
|
|
ASSERT_EQ(
|
|
hipMemcpy(d_buf, host_buf, M * N * elem_size, hipMemcpyHostToDevice),
|
|
hipSuccess);
|
|
const uint32_t call_id = hipblaslt_check_numerics_begin_call(rh);
|
|
ASSERT_EQ(call_id, 1u);
|
|
ASSERT_TRUE(hipblaslt_check_numerics_scan_D(
|
|
rh, nullptr, call_id, M, N, 1, dt, d_buf, M, M * N, false)
|
|
== rocblaslt_status_success);
|
|
uint32_t out = 0;
|
|
EXPECT_HIPBLAS_STATUS(hipblasLtCheckNumericsDrain(h, &out),
|
|
HIPBLAS_STATUS_SUCCESS);
|
|
ASSERT_EQ(out, expected_drain);
|
|
ASSERT_EQ(hipFree(d_buf), hipSuccess);
|
|
EXPECT_HIPBLAS_STATUS(hipblasLtDestroy(h), HIPBLAS_STATUS_SUCCESS);
|
|
};
|
|
|
|
{
|
|
std::vector<double> b(16, std::numeric_limits<double>::quiet_NaN());
|
|
scan_one_with_nan(HIP_R_64F, b.data(), sizeof(double), 1u);
|
|
}
|
|
{
|
|
std::vector<hipblasLtHalf> b(16, static_cast<hipblasLtHalf>(NAN));
|
|
scan_one_with_nan(HIP_R_16F, b.data(), sizeof(hipblasLtHalf), 1u);
|
|
}
|
|
{
|
|
// f32 quiet NaN truncates to bf16 0x7FC0 (exp=0xFF, mantissa nonzero) -- still NaN.
|
|
std::vector<hip_bfloat16> b(16,
|
|
hip_bfloat16(std::numeric_limits<float>::quiet_NaN()));
|
|
scan_one_with_nan(HIP_R_16BF, b.data(), sizeof(hip_bfloat16), 1u);
|
|
}
|
|
{
|
|
// FNUZ NaN bit pattern (all f8/bf8 fnuz: 0x80).
|
|
hipblaslt_f8_fnuz nv;
|
|
nv.__x = 0x80;
|
|
std::vector<hipblaslt_f8_fnuz> b(16, nv);
|
|
scan_one_with_nan(HIP_R_8F_E4M3_FNUZ, b.data(), sizeof(hipblaslt_f8_fnuz), 1u);
|
|
}
|
|
{
|
|
hipblaslt_bf8_fnuz nv;
|
|
nv.__x = 0x80;
|
|
std::vector<hipblaslt_bf8_fnuz> b(16, nv);
|
|
scan_one_with_nan(HIP_R_8F_E5M2_FNUZ, b.data(), sizeof(hipblaslt_bf8_fnuz), 1u);
|
|
}
|
|
{
|
|
// OCP E4M3 canonical NaN: 0x7f.
|
|
hipblaslt_f8 nv;
|
|
nv.__x = 0x7f;
|
|
std::vector<hipblaslt_f8> b(16, nv);
|
|
scan_one_with_nan(HIP_R_8F_E4M3, b.data(), sizeof(hipblaslt_f8), 1u);
|
|
}
|
|
{
|
|
// OCP E5M2 NaN: any of 0x7d/0x7e/0x7f (exp=11111, mant!=0). Use 0x7d
|
|
// to match hipblaslt_isnan coverage above.
|
|
hipblaslt_bf8 nv;
|
|
nv.__x = 0x7d;
|
|
std::vector<hipblaslt_bf8> b(16, nv);
|
|
scan_one_with_nan(HIP_R_8F_E5M2, b.data(), sizeof(hipblaslt_bf8), 1u);
|
|
}
|
|
|
|
// Default-arm silent skip: integer dtypes hit the dispatcher's `default`
|
|
// and must return success without touching the flag.
|
|
{
|
|
reset_env();
|
|
setenv("HIPBLASLT_CHECK_NUMERICS", "1", 1);
|
|
hipblasLtHandle_t h = nullptr;
|
|
EXPECT_HIPBLAS_STATUS(hipblasLtCreate(&h), HIPBLAS_STATUS_SUCCESS);
|
|
rocblaslt_handle rh = (rocblaslt_handle)h;
|
|
constexpr int64_t M = 4, N = 4;
|
|
// Any non-zero pattern; integer arms must NOT inspect it.
|
|
std::vector<int8_t> h_buf(M * N, static_cast<int8_t>(0xFF));
|
|
int8_t* d_buf = nullptr;
|
|
ASSERT_EQ(hipMalloc(&d_buf, M * N * sizeof(int8_t)), hipSuccess);
|
|
ASSERT_EQ(
|
|
hipMemcpy(d_buf, h_buf.data(), M * N * sizeof(int8_t), hipMemcpyHostToDevice),
|
|
hipSuccess);
|
|
const uint32_t call_id = hipblaslt_check_numerics_begin_call(rh);
|
|
ASSERT_TRUE(hipblaslt_check_numerics_scan_D(rh, nullptr, call_id, M, N, 1, HIP_R_8I,
|
|
d_buf, M, M * N, false)
|
|
== rocblaslt_status_success);
|
|
uint32_t out = 99;
|
|
EXPECT_HIPBLAS_STATUS(hipblasLtCheckNumericsDrain(h, &out), HIPBLAS_STATUS_SUCCESS);
|
|
ASSERT_EQ(out, 0u); // never tripped
|
|
ASSERT_EQ(hipFree(d_buf), hipSuccess);
|
|
EXPECT_HIPBLAS_STATUS(hipblasLtDestroy(h), HIPBLAS_STATUS_SUCCESS);
|
|
}
|
|
|
|
// STOP_ON_FIRST: env parses; the sticky short_circuit fires after the
|
|
// first NaN; re-drain returns the same call_id (sticky doesn't reset
|
|
// the device flag).
|
|
{
|
|
reset_env();
|
|
setenv("HIPBLASLT_CHECK_NUMERICS", "1", 1);
|
|
setenv("HIPBLASLT_CHECK_NUMERICS_STOP_ON_FIRST", "1", 1);
|
|
hipblasLtHandle_t h = nullptr;
|
|
EXPECT_HIPBLAS_STATUS(hipblasLtCreate(&h), HIPBLAS_STATUS_SUCCESS);
|
|
rocblaslt_handle rh = (rocblaslt_handle)h;
|
|
ASSERT_TRUE(rh->check_numerics_stop_on_first);
|
|
ASSERT_FALSE(rh->check_numerics_short_circuit.load());
|
|
|
|
constexpr int64_t M = 4, N = 4;
|
|
float* d_buf = nullptr;
|
|
ASSERT_EQ(hipMalloc(&d_buf, M * N * sizeof(float)), hipSuccess);
|
|
std::vector<float> h_buf(M * N, std::numeric_limits<float>::quiet_NaN());
|
|
ASSERT_EQ(hipMemcpy(d_buf, h_buf.data(), M * N * sizeof(float),
|
|
hipMemcpyHostToDevice),
|
|
hipSuccess);
|
|
|
|
const uint32_t cid = hipblaslt_check_numerics_begin_call(rh);
|
|
ASSERT_TRUE(hipblaslt_check_numerics_scan_D(rh, nullptr, cid, M, N, 1, HIP_R_32F,
|
|
d_buf, M, M * N, false)
|
|
== rocblaslt_status_success);
|
|
uint32_t out = 0;
|
|
EXPECT_HIPBLAS_STATUS(hipblasLtCheckNumericsDrain(h, &out), HIPBLAS_STATUS_SUCCESS);
|
|
ASSERT_EQ(out, cid);
|
|
// After the sticky drain, short_circuit is set so further scans bail.
|
|
ASSERT_TRUE(rh->check_numerics_short_circuit.load());
|
|
const uint32_t cid2 = hipblaslt_check_numerics_begin_call(rh);
|
|
ASSERT_TRUE(hipblaslt_check_numerics_scan_D(rh, nullptr, cid2, M, N, 1, HIP_R_32F,
|
|
d_buf, M, M * N, false)
|
|
== rocblaslt_status_success);
|
|
// Re-drain returns the same id (device flag was not memset).
|
|
out = 0;
|
|
EXPECT_HIPBLAS_STATUS(hipblasLtCheckNumericsDrain(h, &out), HIPBLAS_STATUS_SUCCESS);
|
|
ASSERT_EQ(out, cid);
|
|
|
|
ASSERT_EQ(hipFree(d_buf), hipSuccess);
|
|
EXPECT_HIPBLAS_STATUS(hipblasLtDestroy(h), HIPBLAS_STATUS_SUCCESS);
|
|
}
|
|
|
|
// SCAN_EVERY runtime: every=3 means scan_D only runs the kernel when
|
|
// call_id % 3 == 0. With 5 calls, only call_id 3 inspects the buffer,
|
|
// so drain returns 3.
|
|
{
|
|
reset_env();
|
|
setenv("HIPBLASLT_CHECK_NUMERICS", "1", 1);
|
|
setenv("HIPBLASLT_CHECK_NUMERICS_SCAN_EVERY", "3", 1);
|
|
hipblasLtHandle_t h = nullptr;
|
|
EXPECT_HIPBLAS_STATUS(hipblasLtCreate(&h), HIPBLAS_STATUS_SUCCESS);
|
|
rocblaslt_handle rh = (rocblaslt_handle)h;
|
|
ASSERT_EQ(rh->check_numerics_scan_every, 3u);
|
|
|
|
constexpr int64_t M = 4, N = 4;
|
|
float* d_buf = nullptr;
|
|
ASSERT_EQ(hipMalloc(&d_buf, M * N * sizeof(float)), hipSuccess);
|
|
std::vector<float> h_buf(M * N, std::numeric_limits<float>::quiet_NaN());
|
|
ASSERT_EQ(hipMemcpy(d_buf, h_buf.data(), M * N * sizeof(float),
|
|
hipMemcpyHostToDevice),
|
|
hipSuccess);
|
|
|
|
for(int i = 0; i < 5; ++i)
|
|
{
|
|
const uint32_t cid = hipblaslt_check_numerics_begin_call(rh);
|
|
ASSERT_TRUE(hipblaslt_check_numerics_scan_D(rh, nullptr, cid, M, N, 1, HIP_R_32F,
|
|
d_buf, M, M * N, false)
|
|
== rocblaslt_status_success);
|
|
}
|
|
uint32_t out = 0;
|
|
EXPECT_HIPBLAS_STATUS(hipblasLtCheckNumericsDrain(h, &out), HIPBLAS_STATUS_SUCCESS);
|
|
ASSERT_EQ(out, 3u);
|
|
|
|
ASSERT_EQ(hipFree(d_buf), hipSuccess);
|
|
EXPECT_HIPBLAS_STATUS(hipblasLtDestroy(h), HIPBLAS_STATUS_SUCCESS);
|
|
}
|
|
|
|
// SCAN_FROM/SCAN_UNTIL window: gates calls outside [from, until]. With
|
|
// from=3, until=4 and 5 NaN-bearing calls, drain returns 3 (the first
|
|
// in-window call).
|
|
{
|
|
reset_env();
|
|
setenv("HIPBLASLT_CHECK_NUMERICS", "1", 1);
|
|
setenv("HIPBLASLT_CHECK_NUMERICS_SCAN_FROM", "3", 1);
|
|
setenv("HIPBLASLT_CHECK_NUMERICS_SCAN_UNTIL", "4", 1);
|
|
hipblasLtHandle_t h = nullptr;
|
|
EXPECT_HIPBLAS_STATUS(hipblasLtCreate(&h), HIPBLAS_STATUS_SUCCESS);
|
|
rocblaslt_handle rh = (rocblaslt_handle)h;
|
|
ASSERT_EQ(rh->check_numerics_scan_from, 3u);
|
|
ASSERT_EQ(rh->check_numerics_scan_until, 4u);
|
|
|
|
constexpr int64_t M = 4, N = 4;
|
|
float* d_buf = nullptr;
|
|
ASSERT_EQ(hipMalloc(&d_buf, M * N * sizeof(float)), hipSuccess);
|
|
std::vector<float> h_buf(M * N, std::numeric_limits<float>::quiet_NaN());
|
|
ASSERT_EQ(hipMemcpy(d_buf, h_buf.data(), M * N * sizeof(float),
|
|
hipMemcpyHostToDevice),
|
|
hipSuccess);
|
|
|
|
for(int i = 0; i < 5; ++i)
|
|
{
|
|
const uint32_t cid = hipblaslt_check_numerics_begin_call(rh);
|
|
ASSERT_TRUE(hipblaslt_check_numerics_scan_D(rh, nullptr, cid, M, N, 1, HIP_R_32F,
|
|
d_buf, M, M * N, false)
|
|
== rocblaslt_status_success);
|
|
}
|
|
uint32_t out = 0;
|
|
EXPECT_HIPBLAS_STATUS(hipblasLtCheckNumericsDrain(h, &out), HIPBLAS_STATUS_SUCCESS);
|
|
ASSERT_EQ(out, 3u);
|
|
|
|
ASSERT_EQ(hipFree(d_buf), hipSuccess);
|
|
EXPECT_HIPBLAS_STATUS(hipblasLtDestroy(h), HIPBLAS_STATUS_SUCCESS);
|
|
}
|
|
|
|
reset_env();
|
|
}
|
|
#endif // CODE_COVERAGE
|