Skip to site navigation (Press enter)
[linuxkernelnewbies] Master-Slave GPU control
Peter Teoh
Mon, 03 Aug 2009 23:00:44 -0700
http://trac2.assembla.com/hoomd/browser/branches/gpu-iface-rewrite/src/utils/GPUWorker.h?rev=994
1
/*
2
Highly Optimized Object-Oriented Molecular Dynamics (HOOMD) Open
3
Source Software License
4
Copyright (c) 2008 Ames Laboratory Iowa State University
5
All rights reserved.
6
7
Redistribution and use of HOOMD, in source and binary forms, with or
8
without modification, are permitted, provided that the following
9
conditions are met:
10
11
* Redistributions of source code must retain the above copyright notice,
12
this list of conditions and the following disclaimer.
13
14
* Redistributions in binary form must reproduce the above copyright
15
notice, this list of conditions and the following disclaimer in the
16
documentation and/or other materials provided with the distribution.
17
18
* Neither the name of the copyright holder nor the names HOOMD's
19
contributors may be used to endorse or promote products derived from this
20
software without specific prior written permission.
21
22
Disclaimer
23
24
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND
25
CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
26
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
27
AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
28
29
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
30
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
36
THE POSSIBILITY OF SUCH DAMAGE.
37
*/
38
39
// $Id$
40
// $URL$
41
42
/*! \file GPUWorker.h
43
\brief Defines the GPUWorker class
44
*/
45
46
// only compile if USE_CUDA is enabled
47
#
ifdef
USE_CUDA
48
49
#
ifndef
__GPUWORKER_H__
50
#
define
__GPUWORKER_H__
51
52
#
include
<deque>
53
#
include
<stdexcept>
54
55
#
include
<boost/function.hpp>
56
#
include
<boost/thread/thread.hpp>
57
#
include
<boost/thread/mutex.hpp>
58
#
include
<boost/thread/condition.hpp>
59
#
include
<boost/scoped_ptr.hpp>
60
61
#
include
<cuda_runtime_api.h>
62
63
//! Implements a worker thread controlling a single GPU
64
/*! CUDA requires one thread per GPU in multiple GPU code. It is not always
65
convenient to write multiple-threaded code where all threads are peers.
66
Sometimes, a master/slave approach can be the simplest and quickest to write.
67
68
GPUWorker provides the underlying worker threads that a master/slave
69
approach needs to execute on multiple GPUs. It is designed so that
70
a \b single thread can own multiple GPUWorkers, each of whom execute on
71
their own GPU. The master thread can call any CUDA function on that GPU
72
by passing a bound boost::function into call() or callAsync(). Internally, these
73
calls are executed inside the worker thread so that they all share the same
74
CUDA context.
75
76
On construction, a GPUWorker is automatically associated with a device. You
77
pass in an integer device number which is used to call cudaSetDevice()
78
in the worker thread.
79
80
After the GPUWorker is constructed, you can make calls on the GPU
81
by submitting them with call(). To queue calls, use callAsync(), but
82
please read carefully and understand the race condition warnings before
83
using callAsync(). sync() can be used to synchronize the master thread
84
with the worker thread. If any called GPU function returns an error,
85
call() (or the sync() after a callAsync()) will throw a std::runtime_error.
86
87
To share a single GPUWorker with multiple objects, use boost::shared_ptr.
88
\code
89
boost::shared_ptr<GPUWorker> gpu(new GPUWorker(dev));
90
gpu->call(whatever...)
91
SomeClass cls(gpu);
92
// now cls can use gpu to execute in the same worker thread as everybody else
93
\endcode
94
95
\warning A single GPUWorker is intended to be used by a \b single master thread
96
(though master threads can use multiple GPUWorkers). If a single GPUWorker is
97
shared amoung multiple threads then ther \e should not be any horrible consequences.
98
All tasks will still be exected in the order in which they
99
are recieved, but sync() becomes ill-defined (how can one synchronize with a worker that
100
may be receiving commands from another master thread?) and consequently all synchronous
101
calls via call() \b may not actually be synchronous leading to weird race conditions for the
102
caller. Then againm calls via call() \b might work due to the inclusion of a mutex lock:
103
still, multiple threads calling a single GPUWorker is an untested configuration.
104
Use at your own risk.
105
106
\note GPUWorker works in both Linux and Windows (tested with VS2005). However,
107
in Windows, you need to define BOOST_BIND_ENABLE_STDCALL in your project options
108
in order to be able to call CUDA runtime API functions with boost::bind.
109
*/
110
class GPUWorker
111
{
112
public
:
113
//! Creates a worker thread and ties it to a particular gpu \a dev
114
GPUWorker(
int
dev);
115
116
//! Destructor
117
~GPUWorker();
118
119
//! Makes a synchronous function call executed by the worker thread
120
void
call(
const
boost::function< cudaError_t (
void
) > &func);
121
122
//! Queues an asynchronous function call to be executed by the worker thread
123
void
callAsync(
const
boost::function< cudaError_t (
void
) > &func);
124
125
//! Blocks the calling thread until all queued calls have been executed
126
void
sync();
127
128
private
:
129
//! Flag to indicate the worker thread is to exit
130
bool m_exit;
131
132
//! Flag to indicate there is work to do
133
bool m_work_to_do;
134
135
//! Error from last cuda call
136
cudaError_t m_last_error;
137
138
//! The queue of function calls to make
139
std
::deque< boost::function< cudaError_t (
void
) > > m_work_queue;
140
141
//! Mutex for accessing m_exit, m_work_queue, m_work_to_do, and m_last_error
142
boost
::mutex m_mutex;
143
144
//! Mutex for syncing after every operation
145
boost
::mutex m_call_mutex;
146
147
//! Condition variable to signal m_work_to_do = true
148
boost
::condition m_cond_work_to_do;
149
150
//! Condition variable to signal m_work_to_do = false (work is complete)
151
boost
::condition m_cond_work_done;
152
153
//! Thread
154
boost
::scoped_ptr<boost::thread> m_thread;
155
156
//! Worker thread loop
157
void
performWorkLoop();
158
};
159
160
161
#
endif
162
#
endif
Previous message
View by thread
View by date
Next message
Reply via email to
Search the site
The Mail Archive home
linuxkernelnewbies - all messages
linuxkernelnewbies - about the list
Expand
Previous message
Next message