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/utility/enumerationhelpers.h"
67 //! GPU device stream names for outputs.
68 const EnumerationArray<DeviceStreamType, std::string> c_deviceStreamNames = {
69 { "non-bonded local", "non-bonded non-local", "PME", "PME-PP transfer", "update" }
72 /*! \brief Non-GPU builds return nullptr instead of streams,
73 * so we have to expect that in such build configurations. */
74 constexpr bool c_canExpectValidStreams = (GMX_GPU != 0);
76 //! Helper function to implement readable testing
77 void expectValidStreams(DeviceStreamManager* manager, std::initializer_list<DeviceStreamType> types)
79 if (c_canExpectValidStreams)
81 for (const DeviceStreamType type : types)
83 SCOPED_TRACE("Testing " + c_deviceStreamNames[type] + " stream.");
84 EXPECT_TRUE(manager->streamIsValid(type));
88 //! Helper function to implement readable testing
89 void expectInvalidStreams(DeviceStreamManager* manager, std::initializer_list<DeviceStreamType> types)
91 for (const DeviceStreamType type : types)
93 SCOPED_TRACE("Testing " + c_deviceStreamNames[type] + " stream.");
94 EXPECT_FALSE(manager->streamIsValid(type));
99 class DeviceStreamManagerTest : public GpuTest
104 TEST_F(DeviceStreamManagerTest, CorrectStreamsAreReturnedOnNonbondedDevice)
106 // It would be nice to test that the priority is high when it can
107 // be, but that requires calling the same API calls we're testing
108 // that we've called, so it is not very useful.
109 const bool useTiming = false;
111 // TODO Is it enough to only test one device?
112 for (const auto* deviceInfo : getDeviceInfos())
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 bool useGpuForPme = false;
121 bool havePpDomainDecomposition = false;
122 bool doGpuPmePpTransfer = false;
123 bool useGpuForUpdate = false;
124 DeviceStreamManager manager(*deviceInfo, useGpuForPme, havePpDomainDecomposition,
125 doGpuPmePpTransfer, useGpuForUpdate, 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 bool useGpuForPme = false;
136 bool havePpDomainDecomposition = true;
137 bool doGpuPmePpTransfer = false;
138 bool useGpuForUpdate = false;
139 DeviceStreamManager manager(*deviceInfo, useGpuForPme, havePpDomainDecomposition,
140 doGpuPmePpTransfer, useGpuForUpdate, 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 bool useGpuForPme = true;
151 bool havePpDomainDecomposition = false;
152 bool doGpuPmePpTransfer = true;
153 bool useGpuForUpdate = false;
154 DeviceStreamManager manager(*deviceInfo, useGpuForPme, havePpDomainDecomposition,
155 doGpuPmePpTransfer, useGpuForUpdate, 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 bool useGpuForPme = true;
166 bool havePpDomainDecomposition = true;
167 bool doGpuPmePpTransfer = true;
168 bool useGpuForUpdate = false;
169 DeviceStreamManager manager(*deviceInfo, useGpuForPme, havePpDomainDecomposition,
170 doGpuPmePpTransfer, useGpuForUpdate, 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 bool useGpuForPme = false;
180 bool havePpDomainDecomposition = false;
181 bool doGpuPmePpTransfer = false;
182 bool useGpuForUpdate = true;
183 DeviceStreamManager manager(*deviceInfo, useGpuForPme, havePpDomainDecomposition,
184 doGpuPmePpTransfer, useGpuForUpdate, 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 bool useGpuForPme = false;
195 bool havePpDomainDecomposition = true;
196 bool doGpuPmePpTransfer = false;
197 bool useGpuForUpdate = true;
198 DeviceStreamManager manager(*deviceInfo, useGpuForPme, havePpDomainDecomposition,
199 doGpuPmePpTransfer, useGpuForUpdate, 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 bool useGpuForPme = true;
209 bool havePpDomainDecomposition = false;
210 bool doGpuPmePpTransfer = true;
211 bool useGpuForUpdate = true;
212 DeviceStreamManager manager(*deviceInfo, useGpuForPme, havePpDomainDecomposition,
213 doGpuPmePpTransfer, useGpuForUpdate, 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 bool useGpuForPme = true;
224 bool havePpDomainDecomposition = true;
225 bool doGpuPmePpTransfer = true;
226 bool useGpuForUpdate = true;
227 DeviceStreamManager manager(*deviceInfo, useGpuForPme, havePpDomainDecomposition,
228 doGpuPmePpTransfer, useGpuForUpdate, useTiming);
230 expectValidStreams(&manager, { DeviceStreamType::Pme, DeviceStreamType::NonBondedLocal,
231 DeviceStreamType::NonBondedNonLocal, DeviceStreamType::PmePpTransfer,
232 DeviceStreamType::UpdateAndConstraints });