Skip to content

Reland - [Offload] Introduce offload-tblgen and initial new API implementation (#108413) #117704

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 23 commits into from
Nov 27, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
08f3bea
[Offload] Introduce offload-tblgen and initial new API implementation
callumfare Sep 12, 2024
41cc771
Fix liboffload_new linking and formatting
callumfare Sep 13, 2024
1f8d9e8
Refactor entry point validation so failures are visible in tracing ou…
callumfare Sep 18, 2024
44abc70
Add Offload API unittests
callumfare Sep 26, 2024
264b1a5
Implement optional error details
callumfare Oct 1, 2024
499bee7
Check in auto-generated Offload files
callumfare Oct 1, 2024
c048c9c
Fix OffloadGenerate target, clang-format generated files
callumfare Oct 2, 2024
8e3ad6b
Fix offload header install location
callumfare Oct 2, 2024
7b374cc
Tidy generated comments etc
callumfare Oct 2, 2024
dbfe0b5
Rework Offload API errors
callumfare Oct 4, 2024
be7e5c0
Add optional code location entry point variants
callumfare Oct 23, 2024
78df0dc
Rework API to avoid multiple returns, add init/shutdown, general refa…
callumfare Oct 25, 2024
d71d04f
Fix style
callumfare Oct 25, 2024
a5efd29
Only check OFFLOAD_TRACE once
callumfare Oct 25, 2024
a118d67
Add offload-tblgen tests
callumfare Oct 25, 2024
d26a36d
Add additional offload-tblgen tests and associated fixes
callumfare Oct 28, 2024
2e2fe45
Add version info to the API definition
callumfare Oct 28, 2024
d73be98
Fix version query; misc style fixes
callumfare Oct 30, 2024
88ed298
Change prefix from `offload` to `ol`
callumfare Oct 31, 2024
f9154fc
Rename new offload library and try to match LLVM style
callumfare Oct 31, 2024
ed14f1d
Fix missing tablegen, tidy Offload tests
callumfare Oct 31, 2024
5e0f8b0
Use SmallVector where possible
callumfare Nov 1, 2024
135f076
Fix const correctness of offload-tblgen
callumfare Nov 26, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Add Offload API unittests
  • Loading branch information
callumfare committed Nov 26, 2024
commit 44abc7065a7c119af4d88c602d6f0cfe37b5998f
7 changes: 5 additions & 2 deletions offload/new-api/src/offload_impl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ using namespace llvm::omp::target::plugin;
struct offload_device_handle_t_ {
int DeviceNum;
GenericDeviceTy &Device;
offload_platform_handle_t Platform;
};

struct offload_platform_handle_t_ {
Expand Down Expand Up @@ -59,7 +60,7 @@ void initPlugins() {
DevNum++) {
if (Platform.Plugin->init_device(DevNum) == OFFLOAD_SUCCESS) {
Platform.Devices.emplace_back(offload_device_handle_t_{
DevNum, Platform.Plugin->getDevice(DevNum)});
DevNum, Platform.Plugin->getDevice(DevNum), &Platform});
}
}
}
Expand Down Expand Up @@ -173,6 +174,8 @@ offload_result_t offloadDeviceGetInfo_impl(offload_device_handle_t hDevice,
};

switch (propName) {
case OFFLOAD_DEVICE_INFO_PLATFORM:
return ReturnValue(hDevice->Platform);
case OFFLOAD_DEVICE_INFO_TYPE:
return ReturnValue(OFFLOAD_DEVICE_TYPE_GPU);
case OFFLOAD_DEVICE_INFO_NAME:
Expand All @@ -183,7 +186,7 @@ offload_result_t offloadDeviceGetInfo_impl(offload_device_handle_t hDevice,
return ReturnValue(
GetInfo({"CUDA Driver Version", "HSA Runtime Version"}).c_str());
default:
return OFFLOAD_RESULT_ERROR_UNSUPPORTED_ENUMERATION;
return OFFLOAD_RESULT_ERROR_INVALID_ENUMERATION;
}

return OFFLOAD_RESULT_SUCCESS;
Expand Down
3 changes: 2 additions & 1 deletion offload/unittests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@ function(add_libompt_unittest test_dirname)
add_unittest(LibomptUnitTests ${test_dirname} ${ARGN})
endfunction()

add_subdirectory(Plugins)
# add_subdirectory(Plugins)
add_subdirectory(OffloadAPI)
12 changes: 12 additions & 0 deletions offload/unittests/OffloadAPI/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
set(PLUGINS_TEST_COMMON offload_new)
set(PLUGINS_TEST_INCLUDE ${LIBOMPTARGET_INCLUDE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/common)

add_libompt_unittest("offload.unittests"
${CMAKE_CURRENT_SOURCE_DIR}/common/environment.cpp
${CMAKE_CURRENT_SOURCE_DIR}/platform/offloadPlatformGet.cpp
${CMAKE_CURRENT_SOURCE_DIR}/platform/offloadPlatformGetInfo.cpp
${CMAKE_CURRENT_SOURCE_DIR}/device/offloadDeviceGet.cpp
${CMAKE_CURRENT_SOURCE_DIR}/device/offloadDeviceGetInfo.cpp)
add_dependencies("offload.unittests" ${PLUGINS_TEST_COMMON})
target_link_libraries("offload.unittests" PRIVATE ${PLUGINS_TEST_COMMON})
target_include_directories("offload.unittests" PRIVATE ${PLUGINS_TEST_INCLUDE})
92 changes: 92 additions & 0 deletions offload/unittests/OffloadAPI/common/environment.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
//===------- Offload API tests - gtest environment ------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "environment.hpp"
#include "fixtures.hpp"
#include "llvm/Support/CommandLine.h"
#include <offload_api.h>

using namespace llvm;

static cl::opt<std::string>
SelectedPlatform("platform", cl::desc("Only test the specified platform"),
cl::value_desc("platform"));

std::ostream &operator<<(std::ostream &Out,
const offload_platform_handle_t &Platform) {
size_t Size;
offloadPlatformGetInfo(Platform, OFFLOAD_PLATFORM_INFO_NAME, 0, nullptr,
&Size);
std::vector<char> Name(Size);
offloadPlatformGetInfo(Platform, OFFLOAD_PLATFORM_INFO_NAME, Size,
Name.data(), nullptr);
Out << Name.data();
return Out;
}

std::ostream &
operator<<(std::ostream &Out,
const std::vector<offload_platform_handle_t> &Platforms) {
for (auto Platform : Platforms) {
Out << "\n * \"" << Platform << "\"";
}
return Out;
}

const std::vector<offload_platform_handle_t> &TestEnvironment::getPlatforms() {
static std::vector<offload_platform_handle_t> Platforms{};

if (Platforms.empty()) {
uint32_t PlatformCount = 0;
offloadPlatformGet(0, nullptr, &PlatformCount);
if (PlatformCount > 0) {
Platforms.resize(PlatformCount);
offloadPlatformGet(PlatformCount, Platforms.data(), nullptr);
}
}

return Platforms;
}

// Get a single platform, which may be selected by the user.
offload_platform_handle_t TestEnvironment::getPlatform() {
static offload_platform_handle_t Platform = nullptr;
const auto &Platforms = getPlatforms();

if (!Platform) {
if (SelectedPlatform != "") {
for (const auto CandidatePlatform : Platforms) {
std::stringstream PlatformName;
PlatformName << CandidatePlatform;
if (SelectedPlatform == PlatformName.str()) {
Platform = CandidatePlatform;
return Platform;
}
}
std::cout << "No platform found with the name \"" << SelectedPlatform
<< "\". Choose from:" << Platforms << "\n";
std::exit(1);
} else {
// Pick a single platform. We prefer one that has available devices, but
// just pick the first initially in case none have any devices.
Platform = Platforms[0];
for (auto CandidatePlatform : Platforms) {
uint32_t NumDevices = 0;
if (offloadDeviceGet(CandidatePlatform, OFFLOAD_DEVICE_TYPE_ALL, 0,
nullptr, &NumDevices) == OFFLOAD_RESULT_SUCCESS) {
if (NumDevices > 0) {
Platform = CandidatePlatform;
break;
}
}
}
}
}

return Platform;
}
17 changes: 17 additions & 0 deletions offload/unittests/OffloadAPI/common/environment.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
//===------- Offload API tests - gtest environment ------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#pragma once

#include <gtest/gtest.h>
#include <offload_api.h>

namespace TestEnvironment {
const std::vector<offload_platform_handle_t> &getPlatforms();
offload_platform_handle_t getPlatform();
} // namespace TestEnvironment
54 changes: 54 additions & 0 deletions offload/unittests/OffloadAPI/common/fixtures.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
//===------- Offload API tests - gtest fixtures --==-----------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include <gtest/gtest.h>
#include <offload_api.h>
#include <offload_print.hpp>

#include "environment.hpp"

#pragma once

#ifndef ASSERT_SUCCESS
#define ASSERT_SUCCESS(ACTUAL) ASSERT_EQ(OFFLOAD_RESULT_SUCCESS, ACTUAL)
#endif

#define RETURN_ON_FATAL_FAILURE(...) \
__VA_ARGS__; \
if (this->HasFatalFailure() || this->IsSkipped()) { \
return; \
} \
(void)0

struct offloadPlatformTest : ::testing::Test {
void SetUp() override {
RETURN_ON_FATAL_FAILURE(::testing::Test::SetUp());

Platform = TestEnvironment::getPlatform();
ASSERT_NE(Platform, nullptr);
}

offload_platform_handle_t Platform;
};

struct offloadDeviceTest : offloadPlatformTest {
void SetUp() override {
RETURN_ON_FATAL_FAILURE(offloadPlatformTest::SetUp());

uint32_t NumDevices;
ASSERT_SUCCESS(offloadDeviceGet(Platform, OFFLOAD_DEVICE_TYPE_ALL, 0,
nullptr, &NumDevices));
if (NumDevices == 0) {
GTEST_SKIP() << "No available devices on this platform.";
}
ASSERT_SUCCESS(offloadDeviceGet(Platform, OFFLOAD_DEVICE_TYPE_ALL, 1,
&Device, nullptr));
}

offload_device_handle_t Device;
};
41 changes: 41 additions & 0 deletions offload/unittests/OffloadAPI/device/offloadDeviceGet.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
//===------- Offload API tests - offloadDeviceGet -------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "../common/fixtures.hpp"
#include <gtest/gtest.h>
#include <offload_api.h>

using offloadDeviceGetTest = offloadPlatformTest;

TEST_F(offloadDeviceGetTest, Success) {
uint32_t Count = 0;
ASSERT_SUCCESS(
offloadDeviceGet(Platform, OFFLOAD_DEVICE_TYPE_ALL, 0, nullptr, &Count));
ASSERT_NE(Count, 0lu);
std::vector<offload_device_handle_t> Devices(Count);
ASSERT_SUCCESS(offloadDeviceGet(Platform, OFFLOAD_DEVICE_TYPE_ALL, Count,
Devices.data(), nullptr));
for (auto Device : Devices) {
ASSERT_NE(nullptr, Device);
}
}

TEST_F(offloadDeviceGetTest, SuccessSubsetOfDevices) {
uint32_t Count;
ASSERT_SUCCESS(
offloadDeviceGet(Platform, OFFLOAD_DEVICE_TYPE_ALL, 0, nullptr, &Count));
if (Count < 2) {
GTEST_SKIP() << "Only one device is available on this platform.";
}
std::vector<offload_device_handle_t> Devices(Count - 1);
ASSERT_SUCCESS(offloadDeviceGet(Platform, OFFLOAD_DEVICE_TYPE_ALL, Count - 1,
Devices.data(), nullptr));
for (auto Device : Devices) {
ASSERT_NE(nullptr, Device);
}
}
102 changes: 102 additions & 0 deletions offload/unittests/OffloadAPI/device/offloadDeviceGetInfo.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
//===------- Offload API tests - offloadDeviceGetInfo ---------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "../common/fixtures.hpp"
#include <gtest/gtest.h>
#include <offload_api.h>

struct offloadDeviceGetInfoTest
: offloadDeviceTest,
::testing::WithParamInterface<offload_device_info_t> {

void SetUp() override { RETURN_ON_FATAL_FAILURE(offloadDeviceTest::SetUp()); }
};

// TODO: We could autogenerate the list of enum values
INSTANTIATE_TEST_SUITE_P(
, offloadDeviceGetInfoTest,
::testing::Values(OFFLOAD_DEVICE_INFO_TYPE, OFFLOAD_DEVICE_INFO_PLATFORM,
OFFLOAD_DEVICE_INFO_NAME, OFFLOAD_DEVICE_INFO_VENDOR,
OFFLOAD_DEVICE_INFO_DRIVER_VERSION),
[](const ::testing::TestParamInfo<offload_device_info_t> &info) {
std::stringstream ss;
ss << info.param;
return ss.str();
});

// TODO: We could autogenerate this
std::unordered_map<offload_device_info_t, size_t> DeviceInfoSizeMap = {
{OFFLOAD_DEVICE_INFO_TYPE, sizeof(offload_device_type_t)},
{OFFLOAD_DEVICE_INFO_PLATFORM, sizeof(offload_platform_handle_t)},
};

TEST_P(offloadDeviceGetInfoTest, Success) {
offload_device_info_t InfoType = GetParam();
size_t Size = 0;

ASSERT_SUCCESS(offloadDeviceGetInfo(Device, InfoType, 0, nullptr, &Size));
auto ExpectedSize = DeviceInfoSizeMap.find(InfoType);
if (ExpectedSize != DeviceInfoSizeMap.end()) {
ASSERT_EQ(Size, ExpectedSize->second);
} else {
ASSERT_NE(Size, 0lu);
}

std::vector<char> InfoData(Size);
ASSERT_SUCCESS(
offloadDeviceGetInfo(Device, InfoType, Size, InfoData.data(), nullptr));

if (InfoType == OFFLOAD_DEVICE_INFO_PLATFORM) {
auto *ReturnedPlatform =
reinterpret_cast<offload_platform_handle_t *>(InfoData.data());
ASSERT_EQ(Platform, *ReturnedPlatform);
}
}

TEST_F(offloadDeviceGetInfoTest, InvalidNullHandleDevice) {
offload_device_type_t DeviceType;
ASSERT_EQ(OFFLOAD_RESULT_ERROR_INVALID_NULL_HANDLE,
offloadDeviceGetInfo(nullptr, OFFLOAD_DEVICE_INFO_TYPE,
sizeof(offload_device_type_t), &DeviceType,
nullptr));
}

TEST_F(offloadDeviceGetInfoTest, InvalidEnumerationInfoType) {
offload_device_type_t DeviceType;
ASSERT_EQ(OFFLOAD_RESULT_ERROR_INVALID_ENUMERATION,
offloadDeviceGetInfo(Device, OFFLOAD_DEVICE_INFO_FORCE_UINT32,
sizeof(offload_device_type_t), &DeviceType,
nullptr));
}

TEST_F(offloadDeviceGetInfoTest, InvalidSizePropSize) {
offload_device_type_t DeviceType;
ASSERT_EQ(OFFLOAD_RESULT_ERROR_INVALID_SIZE,
offloadDeviceGetInfo(Device, OFFLOAD_DEVICE_INFO_TYPE, 0,
&DeviceType, nullptr));
}

TEST_F(offloadDeviceGetInfoTest, InvalidSizePropSizeSmall) {
offload_device_type_t DeviceType;
ASSERT_EQ(OFFLOAD_RESULT_ERROR_INVALID_SIZE,
offloadDeviceGetInfo(Device, OFFLOAD_DEVICE_INFO_TYPE,
sizeof(DeviceType) - 1, &DeviceType, nullptr));
}

TEST_F(offloadDeviceGetInfoTest, InvalidNullPointerPropValue) {
offload_device_type_t DeviceType;
ASSERT_EQ(OFFLOAD_RESULT_ERROR_INVALID_NULL_POINTER,
offloadDeviceGetInfo(Device, OFFLOAD_DEVICE_INFO_TYPE,
sizeof(DeviceType), nullptr, nullptr));
}

TEST_F(offloadDeviceGetInfoTest, InvalidNullPointerPropSizeRet) {
ASSERT_EQ(OFFLOAD_RESULT_ERROR_INVALID_NULL_POINTER,
offloadDeviceGetInfo(Device, OFFLOAD_DEVICE_INFO_TYPE, 0, nullptr,
nullptr));
}
28 changes: 28 additions & 0 deletions offload/unittests/OffloadAPI/platform/offloadPlatformGet.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
//===------- Offload API tests - offloadPlatformGet -----------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include <gtest/gtest.h>
#include <offload_api.h>
#include "../common/fixtures.hpp"

using offloadPlatformGetTest = ::testing::Test;

TEST_F(offloadPlatformGetTest, Success) {
uint32_t PlatformCount;
ASSERT_SUCCESS(offloadPlatformGet(0, nullptr, &PlatformCount));
std::vector<offload_platform_handle_t> Platforms(PlatformCount);
ASSERT_SUCCESS(offloadPlatformGet(PlatformCount, Platforms.data(), nullptr));
}

TEST_F(offloadPlatformGetTest, InvalidNumEntries) {
uint32_t PlatformCount;
ASSERT_SUCCESS(offloadPlatformGet(0, nullptr, &PlatformCount));
std::vector<offload_platform_handle_t> Platforms(PlatformCount);
ASSERT_EQ(offloadPlatformGet(0, Platforms.data(), nullptr),
OFFLOAD_RESULT_ERROR_INVALID_SIZE);
}
Loading