Skip to content

Commit

Permalink
Add KokkosFFT::initialize and KokkosFFT::finalize
Browse files Browse the repository at this point in the history
  • Loading branch information
Yuuichi Asahi committed Jan 13, 2025
1 parent d991b0c commit 673b484
Show file tree
Hide file tree
Showing 4 changed files with 275 additions and 0 deletions.
79 changes: 79 additions & 0 deletions fft/src/KokkosFFT_Core.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
// SPDX-FileCopyrightText: (C) The kokkos-fft development team, see COPYRIGHT.md file
//
// SPDX-License-Identifier: MIT OR Apache-2.0 WITH LLVM-exception

#include <Kokkos_Core.hpp>
#include "KokkosFFT_Core.hpp"
#include "KokkosFFT_default_types.hpp"

namespace {
bool g_is_initialized = false;
bool g_is_finalized = false;

bool kokkosfft_initialize_was_called() {
return KokkosFFT::is_initialized() || KokkosFFT::is_finalized();
}
bool kokkosfft_finalize_was_called() { return KokkosFFT::is_finalized(); }

void initialize_internal() {
KokkosFFT::Impl::initialize_host();
KokkosFFT::Impl::initialize_device();
}

void finalize_internal() {
KokkosFFT::Impl::finalize_host();
KokkosFFT::Impl::finalize_device();
}
} // namespace

[[nodiscard]] bool KokkosFFT::is_initialized() noexcept {
return g_is_initialized;
}

[[nodiscard]] bool KokkosFFT::is_finalized() noexcept { return g_is_finalized; }

void KokkosFFT::initialize() {
if (!(Kokkos::is_initialized() || Kokkos::is_finalized())) {
Kokkos::abort(
"Error: KokkosFFT::initialize() must not be called before initializing "
"Kokkos.\n");
}
if (Kokkos::is_finalized()) {
Kokkos::abort(
"Error: KokkosFFT::initialize() must not be called after finalizing "
"Kokkos.\n");
}
if (kokkosfft_initialize_was_called()) {
Kokkos::abort(
"Error: KokkosFFT::initialize() has already been called."
" KokkosFFT can be initialized at most once.\n");
}
initialize_internal();
g_is_initialized = true;
}

void KokkosFFT::finalize() {
if (!(Kokkos::is_initialized() || Kokkos::is_finalized())) {
Kokkos::abort(
"Error: KokkosFFT::finalize() may only be called after Kokkos has been "
"initialized.\n");
}
if (Kokkos::is_finalized()) {
Kokkos::abort(
"Error: KokkosFFT::finalize() must be called before finalizing "
"Kokkos.\n");
}

if (!kokkosfft_initialize_was_called()) {
Kokkos::abort(
"Error: KokkosFFT::finalize() may only be called after KokkosFFT has "
"been "
"initialized.\n");
}
if (kokkosfft_finalize_was_called()) {
Kokkos::abort("Error: KokkosFFT::finalize() has already been called.\n");
}
finalize_internal();
g_is_initialized = false;
g_is_finalized = true;
}
17 changes: 17 additions & 0 deletions fft/src/KokkosFFT_Core.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// SPDX-FileCopyrightText: (C) The kokkos-fft development team, see COPYRIGHT.md file
//
// SPDX-License-Identifier: MIT OR Apache-2.0 WITH LLVM-exception

#ifndef KOKKOSFFT_CORE_HPP
#define KOKKOSFFT_CORE_HPP

namespace KokkosFFT {
void initialize();

[[nodiscard]] bool is_initialized() noexcept;
[[nodiscard]] bool is_finalized() noexcept;

void finalize();
} // namespace KokkosFFT

#endif
168 changes: 168 additions & 0 deletions fft/unit_test/Test_InitializeFinalize.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
#include <gtest/gtest.h>
#include <Kokkos_Core.hpp>
#include "KokkosFFT_Core.hpp"

/**
* Fixture that checks Kokkos is neither initialized nor finalized before and
* after each test.
*/
class KokkosFFTExecutionEnvironmentNeverInitialized : public ::testing::Test {
static void checkNeverInitialized() {
ASSERT_FALSE(Kokkos::is_initialized());
ASSERT_FALSE(Kokkos::is_finalized());
ASSERT_FALSE(KokkosFFT::is_initialized());
ASSERT_FALSE(KokkosFFT::is_finalized());
}

protected:
void SetUp() override { checkNeverInitialized(); }
void TearDown() override { checkNeverInitialized(); }
};

namespace {
using InitializeFinalize_DeathTest =
KokkosFFTExecutionEnvironmentNeverInitialized;
using InitializeFinalize_Test = KokkosFFTExecutionEnvironmentNeverInitialized;

TEST_F(InitializeFinalize_DeathTest, initialize) {
::testing::FLAGS_gtest_death_test_style = "threadsafe";

// Valid usage
EXPECT_EXIT(
{
Kokkos::initialize();
KokkosFFT::initialize();
KokkosFFT::finalize();
Kokkos::finalize();
std::exit(EXIT_SUCCESS);
},
::testing::ExitedWithCode(EXIT_SUCCESS), "");

// KokkosFFT is initialized twice
EXPECT_DEATH(
{
Kokkos::initialize();
KokkosFFT::initialize();
KokkosFFT::initialize();
Kokkos::finalize();
},
"Error: KokkosFFT::initialize\\(\\) has already been called. KokkosFFT "
"can be "
"initialized at most once\\.");

// KokkosFFT is initialized twice after finalize
EXPECT_DEATH(
{
Kokkos::initialize();
KokkosFFT::initialize();
KokkosFFT::finalize();
KokkosFFT::initialize();
Kokkos::finalize();
},
"Error: KokkosFFT::initialize\\(\\) has already been called. KokkosFFT "
"can be "
"initialized at most once\\.");

// KokkosFFT is initialized before Kokkos initialization
EXPECT_DEATH(
{
KokkosFFT::initialize();
Kokkos::initialize();
Kokkos::finalize();
},
"Error: KokkosFFT::initialize\\(\\) must not be called before "
"initializing Kokkos\\.");

// KokkosFFT is initialized after Kokkos finalization
EXPECT_DEATH(
{
Kokkos::initialize();
Kokkos::finalize();
KokkosFFT::initialize();
},
"Error: KokkosFFT::initialize\\(\\) must not be called after finalizing "
"Kokkos\\.");
}

TEST_F(InitializeFinalize_DeathTest, finalize) {
::testing::FLAGS_gtest_death_test_style = "threadsafe";

// KokkosFFT is not initialized
EXPECT_DEATH(
{
Kokkos::initialize();
KokkosFFT::finalize();
Kokkos::finalize();
},
"Error: KokkosFFT::finalize\\(\\) may only be called after KokkosFFT has "
"been initialized\\.");

// KokkosFFT is finalized twice
EXPECT_DEATH(
{
Kokkos::initialize();
KokkosFFT::initialize();
KokkosFFT::finalize();
KokkosFFT::finalize();
Kokkos::finalize();
},
"Error: KokkosFFT::finalize\\(\\) has already been called\\.");

// KokkosFFT is finalized before Kokkos initialization
EXPECT_DEATH(
{
KokkosFFT::finalize();
Kokkos::initialize();
Kokkos::finalize();
},
"Error: KokkosFFT::finalize\\(\\) may only be called after Kokkos has "
"been initialized\\.");

// KokkosFFT is finalized after Kokkos finalization
EXPECT_DEATH(
{
Kokkos::initialize();
KokkosFFT::initialize();
Kokkos::finalize();
KokkosFFT::finalize();
},
"Error: KokkosFFT::finalize\\(\\) must be called before finalizing "
"Kokkos\\.");
}

TEST_F(InitializeFinalize_Test, is_initialized) {
EXPECT_EXIT(
{
Kokkos::initialize();
bool success = true;
success &= !KokkosFFT::is_initialized();
std::cout << "success" << success << std::endl;
KokkosFFT::initialize();
success &= KokkosFFT::is_initialized();
std::cout << "success" << success << std::endl;
KokkosFFT::finalize();
success &= !KokkosFFT::is_initialized();
std::cout << "success" << success << std::endl;
Kokkos::finalize();
std::exit(success ? EXIT_SUCCESS : EXIT_FAILURE);
},
::testing::ExitedWithCode(EXIT_SUCCESS), "");
}

TEST_F(InitializeFinalize_Test, is_finalized) {
EXPECT_EXIT(
{
Kokkos::initialize();
bool success = true;
success &= !KokkosFFT::is_finalized();
KokkosFFT::initialize();
success &= !KokkosFFT::is_finalized();
KokkosFFT::finalize();
success &= KokkosFFT::is_finalized();
std::exit(success ? EXIT_SUCCESS : EXIT_FAILURE);
Kokkos::finalize();
},
::testing::ExitedWithCode(EXIT_SUCCESS), "");
}

} // namespace
11 changes: 11 additions & 0 deletions fft/unit_test/Test_MainNoInit.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// SPDX-FileCopyrightText: (C) 2022 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
// SPDX-FileCopyrightText: Under the terms of Contract DE-NA0003525 with NTESS, the U.S. Government retains certain rights in this software.
//
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

#include <gtest/gtest.h>

int main(int argc, char* argv[]) {
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}

0 comments on commit 673b484

Please sign in to comment.