2 * This file is part of the GROMACS molecular simulation package.
4 * Copyright (c) 2017,2018,2019,2020, by the GROMACS development team, led by
5 * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
6 * and including many others, as listed in the AUTHORS file in the
7 * top-level source directory and at http://www.gromacs.org.
9 * GROMACS is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public License
11 * as published by the Free Software Foundation; either version 2.1
12 * of the License, or (at your option) any later version.
14 * GROMACS is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with GROMACS; if not, see
21 * http://www.gnu.org/licenses, or write to the Free Software Foundation,
22 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24 * If you want to redistribute modifications to GROMACS, please
25 * consider that scientific software is very special. Version
26 * control is crucial - bugs must be traceable. We will be happy to
27 * consider code for inclusion in the official distribution, but
28 * derived work must not be called official GROMACS. Details are found
29 * in the README & COPYING files - if they are missing, get the
30 * official version at http://www.gromacs.org.
32 * To help us fund GROMACS development, we humbly ask that you cite
33 * the research papers on the package. Check out http://www.gromacs.org.
36 * \brief Tests GPU stream manager
38 * \author Mark Abraham <mark.j.abraham@gmail.com>
39 * \author Artem Zhmurov <zhmurov@gmail.com>
41 * \ingroup module_gpu_utils
45 #include "gromacs/gpu_utils/device_stream_manager.h"
49 #include <initializer_list>
52 #include <gtest/gtest.h>
54 #include "gromacs/mdtypes/simulation_workload.h"
55 #include "gromacs/utility/enumerationhelpers.h"
68 //! GPU device stream names for outputs.
69 const EnumerationArray<DeviceStreamType, std::string> c_deviceStreamNames = {
70 { "non-bonded local", "non-bonded non-local", "PME", "PME-PP transfer", "update" }
73 /*! \brief Non-GPU builds return nullptr instead of streams,
74 * so we have to expect that in such build configurations. */
75 constexpr bool c_canExpectValidStreams = (GMX_GPU != 0);
77 //! Helper function to implement readable testing
78 void expectValidStreams(DeviceStreamManager* manager, std::initializer_list<DeviceStreamType> types)
80 if (c_canExpectValidStreams)
82 for (const DeviceStreamType type : types)
84 SCOPED_TRACE("Testing " + c_deviceStreamNames[type] + " stream.");
85 EXPECT_TRUE(manager->streamIsValid(type));
89 //! Helper function to implement readable testing
90 void expectInvalidStreams(DeviceStreamManager* manager, std::initializer_list<DeviceStreamType> types)
92 for (const DeviceStreamType type : types)
94 SCOPED_TRACE("Testing " + c_deviceStreamNames[type] + " stream.");
95 EXPECT_FALSE(manager->streamIsValid(type));
100 class DeviceStreamManagerTest : public GpuTest
105 TEST_F(DeviceStreamManagerTest, CorrectStreamsAreReturnedOnNonbondedDevice)
107 // It would be nice to test that the priority is high when it can
108 // be, but that requires calling the same API calls we're testing
109 // that we've called, so it is not very useful.
110 const bool useTiming = false;
112 for (const auto& deviceInfo : getDeviceInfoList())
114 EXPECT_FALSE(deviceInfo == nullptr)
115 << "Device information should be provided for the GPU builds.";
116 // Test all the different cases successively.
119 SCOPED_TRACE("No DD, no PME rank, no GPU update");
120 SimulationWorkload simulationWork;
121 simulationWork.useGpuPme = false;
122 simulationWork.useGpuPmePpCommunication = false;
123 simulationWork.useGpuUpdate = false;
124 bool havePpDomainDecomposition = false;
125 DeviceStreamManager manager(*deviceInfo, havePpDomainDecomposition, simulationWork, useTiming);
127 expectValidStreams(&manager, { DeviceStreamType::NonBondedLocal });
128 expectInvalidStreams(&manager, { DeviceStreamType::NonBondedNonLocal,
129 DeviceStreamType::Pme, DeviceStreamType::PmePpTransfer,
130 DeviceStreamType::UpdateAndConstraints });
134 SCOPED_TRACE("With DD, no PME rank, no GPU update");
135 SimulationWorkload simulationWork;
136 simulationWork.useGpuPme = false;
137 simulationWork.useGpuPmePpCommunication = false;
138 simulationWork.useGpuUpdate = false;
139 bool havePpDomainDecomposition = true;
140 DeviceStreamManager manager(*deviceInfo, havePpDomainDecomposition, simulationWork, useTiming);
142 expectValidStreams(&manager, { DeviceStreamType::NonBondedLocal,
143 DeviceStreamType::NonBondedNonLocal });
144 expectInvalidStreams(&manager, { DeviceStreamType::Pme, DeviceStreamType::PmePpTransfer,
145 DeviceStreamType::UpdateAndConstraints });
149 SCOPED_TRACE("No DD, with PME rank, no GPU update");
150 SimulationWorkload simulationWork;
151 simulationWork.useGpuPme = true;
152 simulationWork.useGpuPmePpCommunication = true;
153 simulationWork.useGpuUpdate = false;
154 bool havePpDomainDecomposition = false;
155 DeviceStreamManager manager(*deviceInfo, havePpDomainDecomposition, simulationWork, useTiming);
157 expectValidStreams(&manager, { DeviceStreamType::Pme, DeviceStreamType::NonBondedLocal,
158 DeviceStreamType::PmePpTransfer,
159 DeviceStreamType::UpdateAndConstraints });
160 expectInvalidStreams(&manager, { DeviceStreamType::NonBondedNonLocal });
164 SCOPED_TRACE("With DD, with PME rank, no GPU update");
165 SimulationWorkload simulationWork;
166 simulationWork.useGpuPme = true;
167 simulationWork.useGpuPmePpCommunication = true;
168 simulationWork.useGpuUpdate = false;
169 bool havePpDomainDecomposition = true;
170 DeviceStreamManager manager(*deviceInfo, havePpDomainDecomposition, simulationWork, useTiming);
172 expectValidStreams(&manager, { DeviceStreamType::Pme, DeviceStreamType::NonBondedLocal,
173 DeviceStreamType::NonBondedNonLocal, DeviceStreamType::PmePpTransfer,
174 DeviceStreamType::UpdateAndConstraints });
178 SCOPED_TRACE("No DD, no PME rank, with GPU update");
179 SimulationWorkload simulationWork;
180 simulationWork.useGpuPme = false;
181 simulationWork.useGpuPmePpCommunication = false;
182 simulationWork.useGpuUpdate = true;
183 bool havePpDomainDecomposition = false;
184 DeviceStreamManager manager(*deviceInfo, havePpDomainDecomposition, simulationWork, useTiming);
186 expectValidStreams(&manager, { DeviceStreamType::NonBondedLocal,
187 DeviceStreamType::UpdateAndConstraints });
188 expectInvalidStreams(&manager, { DeviceStreamType::NonBondedNonLocal,
189 DeviceStreamType::Pme, DeviceStreamType::PmePpTransfer });
193 SCOPED_TRACE("With DD, no PME rank, with GPU update");
194 SimulationWorkload simulationWork;
195 simulationWork.useGpuPme = false;
196 simulationWork.useGpuPmePpCommunication = false;
197 simulationWork.useGpuUpdate = true;
198 bool havePpDomainDecomposition = true;
199 DeviceStreamManager manager(*deviceInfo, havePpDomainDecomposition, simulationWork, useTiming);
201 expectValidStreams(&manager, { DeviceStreamType::NonBondedLocal, DeviceStreamType::NonBondedNonLocal,
202 DeviceStreamType::UpdateAndConstraints });
203 expectInvalidStreams(&manager, { DeviceStreamType::Pme, DeviceStreamType::PmePpTransfer });
207 SCOPED_TRACE("No DD, with PME rank, with GPU update");
208 SimulationWorkload simulationWork;
209 simulationWork.useGpuPme = true;
210 simulationWork.useGpuPmePpCommunication = true;
211 simulationWork.useGpuUpdate = true;
212 bool havePpDomainDecomposition = false;
213 DeviceStreamManager manager(*deviceInfo, havePpDomainDecomposition, simulationWork, useTiming);
215 expectValidStreams(&manager, { DeviceStreamType::Pme, DeviceStreamType::NonBondedLocal,
216 DeviceStreamType::PmePpTransfer,
217 DeviceStreamType::UpdateAndConstraints });
218 expectInvalidStreams(&manager, { DeviceStreamType::NonBondedNonLocal });
222 SCOPED_TRACE("With DD, with PME rank, with GPU update");
223 SimulationWorkload simulationWork;
224 simulationWork.useGpuPme = true;
225 simulationWork.useGpuPmePpCommunication = true;
226 simulationWork.useGpuUpdate = true;
227 bool havePpDomainDecomposition = true;
228 DeviceStreamManager manager(*deviceInfo, havePpDomainDecomposition, simulationWork, useTiming);
230 expectValidStreams(&manager, { DeviceStreamType::Pme, DeviceStreamType::NonBondedLocal,
231 DeviceStreamType::NonBondedNonLocal, DeviceStreamType::PmePpTransfer,
232 DeviceStreamType::UpdateAndConstraints });