Skip to content

Commit

Permalink
Merge Pull Request #7714 from brian-kelley/Trilinos/PrePascalLaunchBl…
Browse files Browse the repository at this point in the history
…ocking

Automatically Merged using Trilinos Pull Request AutoTester
PR Title: Tpetra: enforce CUDA_LAUNCH_BLOCKING on old arches
PR Author: brian-kelley
  • Loading branch information
trilinos-autotester authored Jul 24, 2020
2 parents 384c62f + 5600ceb commit a127732
Show file tree
Hide file tree
Showing 5 changed files with 207 additions and 1 deletion.
4 changes: 3 additions & 1 deletion packages/tpetra/core/src/Tpetra_Core.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,10 @@
#include <Teuchos_DefaultSerialComm.hpp>

#include <Kokkos_Core.hpp>
#include "Tpetra_Details_checkLaunchBlocking.hpp"

namespace Tpetra {

namespace { // (anonymous)

class HideOutputExceptOnProcess0 {
Expand Down Expand Up @@ -148,7 +150,7 @@ namespace Tpetra {
tpetraInitializedKokkos_ = true;
}
}

Details::checkOldCudaLaunchBlocking();
const bool kokkosIsInitialized =
Kokkos::is_initialized ();
TEUCHOS_TEST_FOR_EXCEPTION
Expand Down
75 changes: 75 additions & 0 deletions packages/tpetra/core/src/Tpetra_Details_checkLaunchBlocking.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
// @HEADER
// ***********************************************************************
//
// Tpetra: Templated Linear Algebra Services Package
// Copyright (2008) Sandia Corporation
//
// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
// the U.S. Government retains certain rights in this software.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// 1. Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// 3. Neither the name of the Corporation nor the names of the
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// ************************************************************************
// @HEADER

#ifndef TPETRA_DETAILS_CHECKLAUNCHBLOCKING_HPP
#define TPETRA_DETAILS_CHECKLAUNCHBLOCKING_HPP

#include "TpetraCore_config.h"
#include <cstdlib>
#include <stdexcept>
#include "Kokkos_Core.hpp"

namespace Tpetra {
namespace Details {
#ifdef HAVE_TPETRACORE_CUDA
//Verify that for pre-Pascal CUDA architectures, $CUDA_LAUNCH_BLOCKING == 1
inline void checkOldCudaLaunchBlocking()
{
if(!Kokkos::is_initialized())
throw std::logic_error("Kokkos must be initialized in order to check CUDA_LAUNCH_BLOCKING setting.");
size_t arch = Kokkos::Cuda::device_arch();
if(arch < 600)
{
//Compiling for Kepler/Maxwell: require launch blocking.
const char* launchBlockingEnv = std::getenv("CUDA_LAUNCH_BLOCKING");
if(!launchBlockingEnv || strcmp(launchBlockingEnv, "1"))
{
throw std::runtime_error(
"Tpetra::initialize(): Kokkos was compiled for an older CUDA architecture than Pascal, but\n"
"the environment variable CUDA_LAUNCH_BLOCKING is either unset or is not \"1\".\n"
"It must be set to \"1\" at runtime.\n");
}
}
}
#else
inline void checkOldCudaLaunchBlocking() {}
#endif
}}

#endif
2 changes: 2 additions & 0 deletions packages/tpetra/core/src/Tpetra_Details_initializeKokkos.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
#include "Tpetra_Details_initializeKokkos.hpp"
#include "Teuchos_GlobalMPISession.hpp"
#include "Kokkos_Core.hpp"
#include "Tpetra_Details_checkLaunchBlocking.hpp"
#include <cstdlib> // std::atexit
#include <string>
#include <vector>
Expand All @@ -64,6 +65,7 @@ initializeKokkos ()
args_c[k] = const_cast<char*> (args[k].c_str ());
}
Kokkos::initialize (narg, narg == 0 ? nullptr : args_c.data ());
checkOldCudaLaunchBlocking();
std::atexit (Kokkos::finalize_all);
}
}
Expand Down
10 changes: 10 additions & 0 deletions packages/tpetra/core/test/Core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -164,3 +164,13 @@ TRIBITS_ADD_EXECUTABLE_AND_TEST(
NUM_MPI_PROCS 1
STANDARD_PASS_OUTPUT
)

IF(TPETRA_ENABLE_CUDA)
TRIBITS_ADD_EXECUTABLE_AND_TEST(
check_launch_blocking
SOURCES check_launch_blocking.cpp
COMM serial mpi
ENVIRONMENT CUDA_LAUNCH_BLOCKING=0
STANDARD_PASS_OUTPUT
)
ENDIF()
117 changes: 117 additions & 0 deletions packages/tpetra/core/test/Core/check_launch_blocking.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
/*
// @HEADER
// ***********************************************************************
//
// Tpetra: Templated Linear Algebra Services Package
// Copyright (2008) Sandia Corporation
//
// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
// the U.S. Government retains certain rights in this software.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// 1. Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// 3. Neither the name of the Corporation nor the names of the
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Questions? Contact Michael A. Heroux (maherou@sandia.gov)
//
// ************************************************************************
// @HEADER
*/

#include "Tpetra_Core.hpp"
#include "Kokkos_Core.hpp"
#include <cstring>

int main(int argc, char** argv)
{
bool success = true;
//These architecture macros are defined in KokkosCore_config.h (included by Core)
#if defined(KOKKOS_ARCH_KEPLER) || defined(KOKKOS_ARCH_MAXWELL)
constexpr bool initializeShouldThrow = true;
#else
constexpr bool initializeShouldThrow = false;
#endif
bool threw = false;
try
{
Tpetra::initialize(&argc, &argv);
}
catch(std::exception& e)
{
//Make sure the error's message is the one about launch blocking
//(it mentions CUDA_LAUNCH_BLOCKING verbatim)
//Otherwise it might be an unrelated exception, in which case this test should fail.
if(!strstr(e.what(), "CUDA_LAUNCH_BLOCKING"))
{
std::cerr << "TEST FAILED: Tpetra::initialize() threw unrelated exception.\n";
success = false;
}
else
{
std::cout << "Tpetra::initialize threw exception because CUDA_LAUNCH_BLOCKING required but not set.\n";
}
threw = true;
}
if(!threw)
{
//Initialization succeeded, so clean up
Tpetra::finalize();
}
else
{
//Tpetra wasn't fully initialized, but Kokkos and MPI might have been.
//Finalize those to avoid extra error messages when test terminates.
if(Kokkos::is_initialized())
{
//Tpetra not fully initialized, but Kokkos was
Kokkos::finalize();
}
#ifdef HAVE_TPETRACORE_MPI
int mpiInitialized = 0;
MPI_Initialized(&mpiInitialized);
if(mpiInitialized)
{
//Tpetra not fully initialized, but MPI was
MPI_Finalize();
}
#endif
}
if(threw && !initializeShouldThrow)
{
std::cerr << "TEST FAILED: Tpetra::initialize() threw an exception when it shouldn't have\n";
std::cerr << "(CUDA arch is >= Pascal, so launch blocking not needed).\n";
success = false;
}
else if(!threw && initializeShouldThrow)
{
std::cerr << "TEST FAILED: Tpetra::initialize() did not catch CUDA_LAUNCH_BLOCKING being unset.\n";
success = false;
}
if(success)
std::cout << "End Result: TEST PASSED\n";
return 0;
}

0 comments on commit a127732

Please sign in to comment.