SYCL: Avoid using no_init read accessor in rocFFT
[alexxy/gromacs.git] / src / gromacs / hardware / prepare_detection.cpp
1 /*
2  * This file is part of the GROMACS molecular simulation package.
3  *
4  * Copyright (c) 2012,2013,2014,2015,2016 by the GROMACS development team.
5  * Copyright (c) 2017,2018,2019,2020,2021, by the GROMACS development team, led by
6  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
7  * and including many others, as listed in the AUTHORS file in the
8  * top-level source directory and at http://www.gromacs.org.
9  *
10  * GROMACS is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Lesser General Public License
12  * as published by the Free Software Foundation; either version 2.1
13  * of the License, or (at your option) any later version.
14  *
15  * GROMACS is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  * Lesser General Public License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public
21  * License along with GROMACS; if not, see
22  * http://www.gnu.org/licenses, or write to the Free Software Foundation,
23  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
24  *
25  * If you want to redistribute modifications to GROMACS, please
26  * consider that scientific software is very special. Version
27  * control is crucial - bugs must be traceable. We will be happy to
28  * consider code for inclusion in the official distribution, but
29  * derived work must not be called official GROMACS. Details are found
30  * in the README & COPYING files - if they are missing, get the
31  * official version at http://www.gromacs.org.
32  *
33  * To help us fund GROMACS development, we humbly ask that you cite
34  * the research papers on the package. Check out http://www.gromacs.org.
35  */
36 /*! \internal \file
37  * \brief Defines routine for activating potentially deactivated cores
38  * so they can be detected.
39  *
40  * The use of std::thread makes for brittle interaction with std
41  * library headers. Its caller also handles GPU detection and
42  * allocation of device-specific data structures. This is more
43  * manageable when separated into two distinct translation units.
44  *
45  * \author Erik Lindahl <erik.lindahl@scilifelab.se>
46  * \author Mark Abraham <mark.j.abraham@gmail.com>
47  * \ingroup module_hardware
48  */
49 #include "gmxpre.h"
50
51 #include "prepare_detection.h"
52
53 #include "config.h"
54
55 #include <cstdio>
56
57 #include <chrono>
58 #include <thread>
59 #include <vector>
60
61 #include "architecture.h"
62
63 #ifdef HAVE_UNISTD_H
64 #    include <unistd.h> // sysconf()
65 #endif
66
67 namespace gmx
68 {
69
70 /*! \brief Utility that does dummy computing for max 2 seconds to spin up cores
71  *
72  *  This routine will check the number of cores configured and online
73  *  (using sysconf), and the spins doing dummy compute operations for up to
74  *  2 seconds, or until all cores have come online. This can be used prior to
75  *  hardware detection for platforms that take unused processors offline.
76  */
77 static void spinUpCore() noexcept
78 {
79 #if defined(HAVE_SYSCONF) && defined(_SC_NPROCESSORS_CONF) && defined(_SC_NPROCESSORS_ONLN)
80     float dummy           = 0.1;
81     int   countConfigured = sysconf(_SC_NPROCESSORS_CONF);    // noexcept
82     auto  start           = std::chrono::steady_clock::now(); // noexcept
83
84     while (sysconf(_SC_NPROCESSORS_ONLN) < countConfigured
85            && std::chrono::steady_clock::now() - start < std::chrono::seconds(2))
86     {
87         for (int i = 1; i < 10000; i++)
88         {
89             dummy /= i;
90         }
91     }
92
93     if (dummy < 0)
94     {
95         printf("This cannot happen, but prevents loop from being optimized away.");
96     }
97 #endif
98 }
99
100 void hardwareTopologyPrepareDetection()
101 {
102 #if defined(HAVE_SYSCONF) && defined(_SC_NPROCESSORS_CONF) \
103         && (defined(THREAD_PTHREADS) || defined(THREAD_WINDOWS))
104
105     // Modify this conditional when/if x86 or PowerPC starts to sleep some cores
106     if (c_architecture != Architecture::X86 && c_architecture != Architecture::PowerPC)
107     {
108         int                      countConfigured = sysconf(_SC_NPROCESSORS_CONF);
109         std::vector<std::thread> workThreads(countConfigured);
110
111         for (auto& t : workThreads)
112         {
113             t = std::thread(spinUpCore);
114         }
115
116         for (auto& t : workThreads)
117         {
118             t.join();
119         }
120     }
121 #endif
122 }
123
124 } // namespace gmx