This moves the OpenCL specific definition into under macro in the main header.
Makes device stream and context definitions more consistent.
# different files and strategies for the different GPU implementation
# flavours.
-gmx_add_unit_test(GpuUtilsUnitTests gpu_utils-test
+gmx_add_unit_test(GpuUtilsUnitTests gpu_utils-test HARDWARE_DETECTION
CPP_SOURCE_FILES
- # Infrastructure
- gputest.cpp
# Tests of code
clfftinitializer.cpp
device_stream_manager.cpp
#include <gtest/gtest.h>
+#include "gromacs/hardware/device_management.h"
#include "gromacs/mdtypes/simulation_workload.h"
#include "gromacs/utility/enumerationhelpers.h"
-#include "gputest.h"
+#include "testutils/test_hardware_environment.h"
namespace gmx
{
}
//! Test fixture
-class DeviceStreamManagerTest : public GpuTest
+class DeviceStreamManagerTest : public ::testing::Test
{
public:
};
// that we've called, so it is not very useful.
const bool useTiming = false;
- for (const auto& deviceInfo : getDeviceInfoList())
+ const auto& testDeviceList = getTestHardwareEnvironment()->getTestDeviceList();
+ for (const auto& testDevice : testDeviceList)
{
- EXPECT_FALSE(deviceInfo == nullptr)
- << "Device information should be provided for the GPU builds.";
- // Test all the different cases successively.
+ const DeviceInformation& deviceInfo = testDevice->deviceInfo();
+ setActiveDevice(deviceInfo);
{
SCOPED_TRACE("No DD, no PME rank, no GPU update");
simulationWork.useGpuPmePpCommunication = false;
simulationWork.useGpuUpdate = false;
bool havePpDomainDecomposition = false;
- DeviceStreamManager manager(*deviceInfo, havePpDomainDecomposition, simulationWork, useTiming);
+ DeviceStreamManager manager(deviceInfo, havePpDomainDecomposition, simulationWork, useTiming);
expectValidStreams(&manager, { DeviceStreamType::NonBondedLocal });
expectInvalidStreams(&manager, { DeviceStreamType::NonBondedNonLocal,
simulationWork.useGpuPmePpCommunication = false;
simulationWork.useGpuUpdate = false;
bool havePpDomainDecomposition = true;
- DeviceStreamManager manager(*deviceInfo, havePpDomainDecomposition, simulationWork, useTiming);
+ DeviceStreamManager manager(deviceInfo, havePpDomainDecomposition, simulationWork, useTiming);
expectValidStreams(&manager, { DeviceStreamType::NonBondedLocal,
DeviceStreamType::NonBondedNonLocal });
simulationWork.useGpuPmePpCommunication = true;
simulationWork.useGpuUpdate = false;
bool havePpDomainDecomposition = false;
- DeviceStreamManager manager(*deviceInfo, havePpDomainDecomposition, simulationWork, useTiming);
+ DeviceStreamManager manager(deviceInfo, havePpDomainDecomposition, simulationWork, useTiming);
expectValidStreams(&manager, { DeviceStreamType::Pme, DeviceStreamType::NonBondedLocal,
DeviceStreamType::PmePpTransfer,
simulationWork.useGpuPmePpCommunication = true;
simulationWork.useGpuUpdate = false;
bool havePpDomainDecomposition = true;
- DeviceStreamManager manager(*deviceInfo, havePpDomainDecomposition, simulationWork, useTiming);
+ DeviceStreamManager manager(deviceInfo, havePpDomainDecomposition, simulationWork, useTiming);
expectValidStreams(&manager, { DeviceStreamType::Pme, DeviceStreamType::NonBondedLocal,
DeviceStreamType::NonBondedNonLocal, DeviceStreamType::PmePpTransfer,
simulationWork.useGpuPmePpCommunication = false;
simulationWork.useGpuUpdate = true;
bool havePpDomainDecomposition = false;
- DeviceStreamManager manager(*deviceInfo, havePpDomainDecomposition, simulationWork, useTiming);
+ DeviceStreamManager manager(deviceInfo, havePpDomainDecomposition, simulationWork, useTiming);
expectValidStreams(&manager, { DeviceStreamType::NonBondedLocal,
DeviceStreamType::UpdateAndConstraints });
simulationWork.useGpuPmePpCommunication = false;
simulationWork.useGpuUpdate = true;
bool havePpDomainDecomposition = true;
- DeviceStreamManager manager(*deviceInfo, havePpDomainDecomposition, simulationWork, useTiming);
+ DeviceStreamManager manager(deviceInfo, havePpDomainDecomposition, simulationWork, useTiming);
expectValidStreams(&manager, { DeviceStreamType::NonBondedLocal, DeviceStreamType::NonBondedNonLocal,
DeviceStreamType::UpdateAndConstraints });
simulationWork.useGpuPmePpCommunication = true;
simulationWork.useGpuUpdate = true;
bool havePpDomainDecomposition = false;
- DeviceStreamManager manager(*deviceInfo, havePpDomainDecomposition, simulationWork, useTiming);
+ DeviceStreamManager manager(deviceInfo, havePpDomainDecomposition, simulationWork, useTiming);
expectValidStreams(&manager, { DeviceStreamType::Pme, DeviceStreamType::NonBondedLocal,
DeviceStreamType::PmePpTransfer,
simulationWork.useGpuPmePpCommunication = true;
simulationWork.useGpuUpdate = true;
bool havePpDomainDecomposition = true;
- DeviceStreamManager manager(*deviceInfo, havePpDomainDecomposition, simulationWork, useTiming);
+ DeviceStreamManager manager(deviceInfo, havePpDomainDecomposition, simulationWork, useTiming);
expectValidStreams(&manager, { DeviceStreamType::Pme, DeviceStreamType::NonBondedLocal,
DeviceStreamType::NonBondedNonLocal, DeviceStreamType::PmePpTransfer,
cl_context_properties properties[] = {
CL_CONTEXT_PLATFORM, reinterpret_cast<cl_context_properties>(deviceInfo.oclPlatformId), 0
};
- // Give uncrustify more space
auto deviceId = deviceInfo.oclDeviceId;
auto context = clCreateContext(properties, 1, &deviceId, nullptr, nullptr, &status);
+++ /dev/null
-/*
- * This file is part of the GROMACS molecular simulation package.
- *
- * Copyright (c) 2017,2018,2019,2020, by the GROMACS development team, led by
- * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
- * and including many others, as listed in the AUTHORS file in the
- * top-level source directory and at http://www.gromacs.org.
- *
- * GROMACS is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public License
- * as published by the Free Software Foundation; either version 2.1
- * of the License, or (at your option) any later version.
- *
- * GROMACS is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with GROMACS; if not, see
- * http://www.gnu.org/licenses, or write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * If you want to redistribute modifications to GROMACS, please
- * consider that scientific software is very special. Version
- * control is crucial - bugs must be traceable. We will be happy to
- * consider code for inclusion in the official distribution, but
- * derived work must not be called official GROMACS. Details are found
- * in the README & COPYING files - if they are missing, get the
- * official version at http://www.gromacs.org.
- *
- * To help us fund GROMACS development, we humbly ask that you cite
- * the research papers on the package. Check out http://www.gromacs.org.
- */
-/*! \internal \file
- * \brief
- * Tests utilities for GPU device allocation and free.
- *
- * \author Mark Abraham <mark.j.abraham@gmail.com>
- */
-#include "gmxpre.h"
-
-#include "gputest.h"
-
-#include <gtest/gtest.h>
-
-#include "gromacs/gpu_utils/gpu_utils.h"
-#include "gromacs/hardware/device_information.h"
-#include "gromacs/hardware/device_management.h"
-#include "gromacs/utility/smalloc.h"
-
-namespace gmx
-{
-namespace test
-{
-
-GpuTest::GpuTest()
-{
- if (canPerformDeviceDetection(nullptr))
- {
- deviceInfoList_ = findDevices();
- }
- // Failing to find valid GPUs does not require further action
-}
-
-GpuTest::~GpuTest() = default;
-
-std::vector<std::unique_ptr<DeviceInformation>>& GpuTest::getDeviceInfoList()
-{
- return deviceInfoList_;
-}
-
-} // namespace test
-} // namespace gmx
+++ /dev/null
-/*
- * This file is part of the GROMACS molecular simulation package.
- *
- * Copyright (c) 2017,2018,2019,2020, by the GROMACS development team, led by
- * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
- * and including many others, as listed in the AUTHORS file in the
- * top-level source directory and at http://www.gromacs.org.
- *
- * GROMACS is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public License
- * as published by the Free Software Foundation; either version 2.1
- * of the License, or (at your option) any later version.
- *
- * GROMACS is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with GROMACS; if not, see
- * http://www.gnu.org/licenses, or write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * If you want to redistribute modifications to GROMACS, please
- * consider that scientific software is very special. Version
- * control is crucial - bugs must be traceable. We will be happy to
- * consider code for inclusion in the official distribution, but
- * derived work must not be called official GROMACS. Details are found
- * in the README & COPYING files - if they are missing, get the
- * official version at http://www.gromacs.org.
- *
- * To help us fund GROMACS development, we humbly ask that you cite
- * the research papers on the package. Check out http://www.gromacs.org.
- */
-/*! \internal \file
- * \brief
- * Declares test fixture testing GPU utility components.
- *
- * \author Mark Abraham <mark.j.abraham@gmail.com>
- */
-#ifndef GMX_GPU_UTILS_TESTS_GPUTEST_H
-#define GMX_GPU_UTILS_TESTS_GPUTEST_H
-
-#include "gmxpre.h"
-
-#include <gtest/gtest.h>
-
-#include "gromacs/hardware/device_management.h"
-
-struct DeviceInformation;
-
-namespace gmx
-{
-namespace test
-{
-
-class GpuTest : public ::testing::Test
-{
-public:
- //! List of all available devices
- std::vector<std::unique_ptr<DeviceInformation>> deviceInfoList_;
-
- GpuTest();
- ~GpuTest() override;
- //! Return a vector of handles, each to a device info for a compatible GPU.
- std::vector<std::unique_ptr<DeviceInformation>>& getDeviceInfoList();
-};
-
-} // namespace test
-} // namespace gmx
-
-#endif
#include <gtest/gtest.h>
#include "gromacs/gpu_utils/gpu_utils.h"
+#include "gromacs/hardware/device_management.h"
#include "gromacs/math/vectypes.h"
#include "gromacs/utility/arrayref.h"
#include "gromacs/utility/real.h"
#include "gromacs/math/tests/testarrayrefs.h"
+#include "testutils/test_hardware_environment.h"
#include "devicetransfers.h"
-#include "gputest.h"
namespace gmx
{
/*! \internal \brief Typed test fixture for infrastructure for
* host-side memory used for GPU transfers. */
template<typename T>
-class HostMemoryTest : public test::GpuTest
+class HostMemoryTest : public ::testing::Test
{
public:
//! Convenience type
TYPED_TEST(HostAllocatorTestCopyable, TransfersWithoutPinningWork)
{
- for (const DeviceInformation& compatibleDeviceInfo : getCompatibleDevices(this->deviceInfoList_))
+ for (const auto& testDevice : getTestHardwareEnvironment()->getTestDeviceList())
{
+ setActiveDevice(testDevice->deviceInfo());
typename TestFixture::VectorType input;
fillInput(&input, 1);
typename TestFixture::VectorType output;
output.resizeWithPadding(input.size());
- runTest(compatibleDeviceInfo, makeArrayRef(input), makeArrayRef(output));
+ runTest(testDevice->deviceInfo(), makeArrayRef(input), makeArrayRef(output));
}
}
TYPED_TEST(HostAllocatorTestCopyable, TransfersWithPinningWorkWithCuda)
{
- for (auto& deviceInfo : this->deviceInfoList_)
+ for (const auto& testDevice : getTestHardwareEnvironment()->getTestDeviceList())
{
+ setActiveDevice(testDevice->deviceInfo());
typename TestFixture::VectorType input;
changePinningPolicy(&input, PinningPolicy::PinnedIfSupported);
fillInput(&input, 1);
changePinningPolicy(&output, PinningPolicy::PinnedIfSupported);
output.resizeWithPadding(input.size());
- runTest(*deviceInfo, makeArrayRef(input), makeArrayRef(output));
+ runTest(testDevice->deviceInfo(), makeArrayRef(input), makeArrayRef(output));
}
}
TYPED_TEST(HostAllocatorTestCopyable, ManualPinningOperationsWorkWithCuda)
{
- if (!canComputeOnDevice())
+ for (const auto& testDevice : getTestHardwareEnvironment()->getTestDeviceList())
{
- return;
+ setActiveDevice(testDevice->deviceInfo());
+ typename TestFixture::VectorType input;
+ changePinningPolicy(&input, PinningPolicy::PinnedIfSupported);
+ EXPECT_TRUE(input.get_allocator().pinningPolicy() == PinningPolicy::PinnedIfSupported);
+ EXPECT_TRUE(input.empty());
+ fillInput(&input, 1);
+ // realloc and copy).
+ auto oldInputData = input.data();
+ changePinningPolicy(&input, PinningPolicy::CannotBePinned);
+ EXPECT_FALSE(isPinned(input));
+ // These cannot be equal as both had to be allocated at the same
+ // time for the contents to be able to be copied.
+ EXPECT_NE(oldInputData, input.data());
+
+ // Switching policy to PinnedIfSupported must pin the buffer (via
+ // realloc and copy).
+ oldInputData = input.data();
+ changePinningPolicy(&input, PinningPolicy::PinnedIfSupported);
+ EXPECT_TRUE(isPinned(input));
+ // These cannot be equal as both had to be allocated at the same
+ // time for the contents to be able to be copied.
+ EXPECT_NE(oldInputData, input.data());
}
-
- typename TestFixture::VectorType input;
- changePinningPolicy(&input, PinningPolicy::PinnedIfSupported);
- EXPECT_TRUE(input.get_allocator().pinningPolicy() == PinningPolicy::PinnedIfSupported);
- EXPECT_EQ(0, input.size());
- EXPECT_EQ(0, input.paddedSize());
- EXPECT_TRUE(input.empty());
- EXPECT_FALSE(isPinned(input)) << "should not be pinned before allocation";
-
- // Fill some contents, which will be pinned because of the policy.
- fillInput(&input, 1);
- EXPECT_TRUE(isPinned(input)) << "should be pinned after allocation";
-
- // Switching policy to CannotBePinned must unpin the buffer (via
- // realloc and copy).
- auto oldInputData = input.data();
- changePinningPolicy(&input, PinningPolicy::CannotBePinned);
- EXPECT_FALSE(isPinned(input)) << "should not be pinned after changing policy to CannotBePinned";
- // These cannot be equal as both had to be allocated at the same
- // time for the contents to be able to be copied.
- EXPECT_NE(oldInputData, input.data());
-
- // Switching policy to PinnedIfSupported must pin the buffer (via
- // realloc and copy).
- oldInputData = input.data();
- changePinningPolicy(&input, PinningPolicy::PinnedIfSupported);
- EXPECT_TRUE(isPinned(input)) << "should be pinned after changing policy to PinnedIfSupported";
- // These cannot be equal as both had to be allocated at the same
- // time for the contents to be able to be copied.
- EXPECT_NE(oldInputData, input.data());
}
#endif
# include "gromacs/utility/real.h"
# include "gromacs/utility/smalloc.h"
-# include "gputest.h"
+# include "testutils/test_hardware_environment.h"
namespace gmx
{
{
//! Test fixture
-using PinnedMemoryCheckerTest = GpuTest;
+using PinnedMemoryCheckerTest = ::testing::Test;
TEST_F(PinnedMemoryCheckerTest, DefaultContainerIsRecognized)
{
- if (!canComputeOnDevice())
- {
- return;
- }
-
- std::vector<real> dummy(3, 1.5);
- EXPECT_FALSE(isHostMemoryPinned(dummy.data()));
-}
-
-TEST_F(PinnedMemoryCheckerTest, NonpinnedContainerIsRecognized)
-{
- if (!canComputeOnDevice())
- {
- return;
- }
-
HostVector<real> dummy(3, 1.5);
changePinningPolicy(&dummy, PinningPolicy::CannotBePinned);
EXPECT_FALSE(isHostMemoryPinned(dummy.data()));
TEST_F(PinnedMemoryCheckerTest, PinnedContainerIsRecognized)
{
- if (!canComputeOnDevice())
- {
- return;
- }
-
HostVector<real> dummy(3, 1.5);
changePinningPolicy(&dummy, PinningPolicy::PinnedIfSupported);
EXPECT_TRUE(isHostMemoryPinned(dummy.data()));
TEST_F(PinnedMemoryCheckerTest, PinningChangesAreRecognized)
{
- if (!canComputeOnDevice())
- {
- return;
- }
-
HostVector<real> dummy(3, 1.5);
changePinningPolicy(&dummy, PinningPolicy::PinnedIfSupported);
EXPECT_TRUE(isHostMemoryPinned(dummy.data())) << "memory starts pinned";
TEST_F(PinnedMemoryCheckerTest, DefaultCBufferIsRecognized)
{
- if (!canComputeOnDevice())
- {
- return;
- }
-
real* dummy;
snew(dummy, 3);
EXPECT_FALSE(isHostMemoryPinned(dummy));
TEST_F(PinnedMemoryCheckerTest, PinnedCBufferIsRecognized)
{
- if (!canComputeOnDevice())
- {
- return;
- }
-
real* dummy = nullptr;
pmalloc(reinterpret_cast<void**>(&dummy), 3 * sizeof(real));
EXPECT_TRUE(isHostMemoryPinned(dummy));
#if GMX_GPU_CUDA
-# include <vector>
-
-# include <gtest/gtest.h>
-
+# include "gromacs/gpu_utils/gputraits.h"
# include "gromacs/hardware/device_management.h"
# include "gromacs/utility/exceptions.h"
+# include "testutils/test_hardware_environment.h"
# include "testutils/testasserts.h"
# include "testutils/testmatchers.h"
//! Test data in RVec format
static const std::vector<RVec> rVecInput = { { 1.0, 2.0, 3.0 }, { 4.0, 5.0, 6.0 } };
-TEST(GpuDataTypesCompatibilityTest, RVecAndFloat3OnHost)
+TEST(GpuDataTypesCompatibilityTest, RVecAndFloat3Host)
{
std::vector<RVec> rVecOutput(rVecInput.size());
convertRVecToFloat3OnHost(rVecOutput, rVecInput);
EXPECT_THAT(rVecInput, testing::Pointwise(RVecEq(ulpTolerance(0)), rVecOutput));
}
-TEST(GpuDataTypesCompatibilityTest, RVecAndFloat3OnDevice)
+TEST(GpuDataTypesCompatibilityTest, RVecAndFloat3Device)
{
- if (canComputeOnDevice())
+ for (const auto& testDevice : getTestHardwareEnvironment()->getTestDeviceList())
{
+ setActiveDevice(testDevice->deviceInfo());
std::vector<RVec> rVecOutput(rVecInput.size());
- convertRVecToFloat3OnDevice(rVecOutput, rVecInput);
+ convertRVecToFloat3OnDevice(rVecOutput, rVecInput, testDevice.get());
EXPECT_THAT(rVecInput, testing::Pointwise(RVecEq(ulpTolerance(0)), rVecOutput));
}
}
}
void convertRVecToFloat3OnDevice(std::vector<gmx::RVec>& /* rVecOutput */,
- const std::vector<gmx::RVec>& /* rVecInput*/)
+ const std::vector<gmx::RVec>& /* rVecInput */,
+ const TestDevice* /* testDevice */)
{
FAIL() << "Can't test float3 and RVec compatibility without CUDA.";
}
}
}
-void convertRVecToFloat3OnDevice(std::vector<gmx::RVec>& h_rVecOutput, const std::vector<gmx::RVec>& h_rVecInput)
+void convertRVecToFloat3OnDevice(std::vector<gmx::RVec>& h_rVecOutput,
+ const std::vector<gmx::RVec>& h_rVecInput,
+ const TestDevice* testDevice)
{
- DeviceInformation deviceInfo;
- const DeviceContext deviceContext(deviceInfo);
- const DeviceStream deviceStream(deviceContext, DeviceStreamPriority::Normal, false);
+ const DeviceContext& deviceContext = testDevice->deviceContext();
+ const DeviceStream& deviceStream = testDevice->deviceStream();
+
+ setActiveDevice(testDevice->deviceInfo());
const int numElements = h_rVecInput.size();
#include <vector>
+#include <gtest/gtest.h>
+
#include "gromacs/math/vectypes.h"
+#include "testutils/test_device.h"
+
namespace gmx
{
*
* \param[out] rVecOutput Data in RVec format for the output.
* \param[in] rVecInput Data in RVec format with the input.
+ * \param[in] testDevice Test herdware environment to get DeviceContext and DeviceStream from.
*/
-void convertRVecToFloat3OnDevice(std::vector<gmx::RVec>& rVecOutput, const std::vector<gmx::RVec>& rVecInput);
+void convertRVecToFloat3OnDevice(std::vector<gmx::RVec>& rVecOutput,
+ const std::vector<gmx::RVec>& rVecInput,
+ const TestDevice* testDevice);
+
} // namespace test
} // namespace gmx