SYCL: Avoid using no_init read accessor in rocFFT
[alexxy/gromacs.git] / src / gromacs / gpu_utils / device_event_ocl.h
1 /*
2  * This file is part of the GROMACS molecular simulation package.
3  *
4  * Copyright (c) 2018,2019,2020,2021, 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.
8  *
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.
13  *
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.
18  *
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.
23  *
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.
31  *
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.
34  */
35 /*! \libinternal \file
36  *  \brief Implements a DeviceEvent class for OpenCL.
37  *
38  *  \author Aleksei Iupinov <a.yupinov@gmail.com>
39  *  \author Andrey Alekseenko <al42and@gmail.com>
40  * \inlibraryapi
41  */
42 #ifndef GMX_GPU_UTILS_DEVICE_EVENT_OCL_H
43 #define GMX_GPU_UTILS_DEVICE_EVENT_OCL_H
44
45 #include "gromacs/gpu_utils/gputraits_ocl.h"
46 #include "gromacs/gpu_utils/oclutils.h"
47 #include "gromacs/utility/exceptions.h"
48 #include "gromacs/utility/gmxassert.h"
49
50 #ifndef DOXYGEN
51
52 class DeviceEvent
53 {
54 public:
55     //! A constructor
56     DeviceEvent() : event_(sc_nullEvent) {}
57     DeviceEvent(cl_event event) : event_(event) {}
58     //! A destructor
59     ~DeviceEvent()
60     {
61         if (isMarked())
62         {
63             // Can not throw in destructor, so not checking for any error
64             clReleaseEvent(event_);
65         }
66     }
67     // Disable copy, move, and assignment. Move can be allowed, but not needed yet.
68     DeviceEvent& operator=(const DeviceEvent&) = delete;
69     DeviceEvent(const DeviceEvent&)            = delete;
70     DeviceEvent& operator=(DeviceEvent&&) = delete;
71     DeviceEvent(DeviceEvent&&)            = delete;
72
73     /*! \brief Marks the synchronization point in the \p stream.
74      * Should be called first and then followed by wait().
75      */
76     inline void mark(const DeviceStream& deviceStream)
77     {
78         reset();
79         cl_int clError = clEnqueueMarkerWithWaitList(deviceStream.stream(), 0, nullptr, &event_);
80         if (CL_SUCCESS != clError)
81         {
82             GMX_THROW(gmx::InternalError("Failed to enqueue the GPU synchronization event: "
83                                          + ocl_get_error_string(clError)));
84         }
85     }
86
87     /*! \brief Synchronizes the host thread on the marked event. */
88     inline void wait()
89     {
90         GMX_RELEASE_ASSERT(isMarked(), "Can not wait for an unmarked event");
91         cl_int clError = clWaitForEvents(1, &event_);
92         if (CL_SUCCESS != clError)
93         {
94             GMX_THROW(gmx::InternalError("Failed to synchronize on the GPU event: "
95                                          + ocl_get_error_string(clError)));
96         }
97     }
98
99     /*! \brief Enqueues a wait for the recorded event in stream \p stream. */
100     inline void enqueueWait(const DeviceStream& deviceStream)
101     {
102         GMX_RELEASE_ASSERT(isMarked(), "Can not enqueue an unmarked event");
103         cl_int clError = clEnqueueBarrierWithWaitList(deviceStream.stream(), 1, &event_, nullptr);
104         if (CL_SUCCESS != clError)
105         {
106             GMX_THROW(gmx::InternalError("Failed to enqueue device barrier for the GPU event: "
107                                          + ocl_get_error_string(clError)));
108         }
109     }
110
111     //!  Checks the completion of the underlying event.
112     inline bool isReady()
113     {
114         GMX_RELEASE_ASSERT(isMarked(), "Can not check the status of unmarked event");
115         cl_int result;
116         cl_int clError = clGetEventInfo(
117                 event_, CL_EVENT_COMMAND_EXECUTION_STATUS, sizeof(cl_int), &result, nullptr);
118         if (CL_SUCCESS != clError)
119         {
120             GMX_THROW(gmx::InternalError("Failed to retrieve event info: " + ocl_get_error_string(clError)));
121         }
122         return (result == CL_COMPLETE);
123     }
124
125     //! Checks whether this object encapsulates an underlying event.
126     inline bool isMarked() const { return event_ != sc_nullEvent; }
127
128     //! Reset (release) the event to unmarked state.
129     inline void reset()
130     {
131         if (isMarked())
132         {
133             cl_int clError = clReleaseEvent(event_);
134             if (CL_SUCCESS != clError)
135             {
136                 GMX_THROW(gmx::InternalError("Failed to release the GPU event: "
137                                              + ocl_get_error_string(clError)));
138             }
139         }
140         event_ = sc_nullEvent;
141     }
142
143 private:
144     cl_event event_;
145
146     //! Magic value to indicate uninitialized state.
147     static constexpr cl_event sc_nullEvent = nullptr;
148 };
149
150 #endif
151
152 #endif