cuda_stream.cpp

Ernest Galbrun, 2014-07-23 02:12 pm

Download (7.5 kB)

 
1
/*M///////////////////////////////////////////////////////////////////////////////////////
2
//
3
//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
4
//
5
//  By downloading, copying, installing or using the software you agree to this license.
6
//  If you do not agree to this license, do not download, install,
7
//  copy or use the software.
8
//
9
//
10
//                           License Agreement
11
//                For Open Source Computer Vision Library
12
//
13
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
14
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
15
// Third party copyrights are property of their respective owners.
16
//
17
// Redistribution and use in source and binary forms, with or without modification,
18
// are permitted provided that the following conditions are met:
19
//
20
//   * Redistribution's of source code must retain the above copyright notice,
21
//     this list of conditions and the following disclaimer.
22
//
23
//   * Redistribution's in binary form must reproduce the above copyright notice,
24
//     this list of conditions and the following disclaimer in the documentation
25
//     and/or other materials provided with the distribution.
26
//
27
//   * The name of the copyright holders may not be used to endorse or promote products
28
//     derived from this software without specific prior written permission.
29
//
30
// This software is provided by the copyright holders and contributors "as is" and
31
// any express or implied warranties, including, but not limited to, the implied
32
// warranties of merchantability and fitness for a particular purpose are disclaimed.
33
// In no event shall the Intel Corporation or contributors be liable for any direct,
34
// indirect, incidental, special, exemplary, or consequential damages
35
// (including, but not limited to, procurement of substitute goods or services;
36
// loss of use, data, or profits; or business interruption) however caused
37
// and on any theory of liability, whether in contract, strict liability,
38
// or tort (including negligence or otherwise) arising in any way out of
39
// the use of this software, even if advised of the possibility of such damage.
40
//
41
//M*/
42
43
#include "precomp.hpp"
44
45
using namespace cv;
46
using namespace cv::cuda;
47
48
////////////////////////////////////////////////////////////////
49
// Stream
50
51
#ifndef HAVE_CUDA
52
53
class cv::cuda::Stream::Impl
54
{
55
public:
56
    Impl(void* ptr = 0)
57
    {
58
        (void) ptr;
59
        throw_no_cuda();
60
    }
61
};
62
63
#else
64
65
class cv::cuda::Stream::Impl
66
{
67
public:
68
    cudaStream_t stream;
69
    Ptr<StackAllocator> stackAllocator_;
70
71
    Impl();
72
    Impl(cudaStream_t stream);
73
74
    ~Impl();
75
};
76
77
cv::cuda::BufferPool::BufferPool(Stream& stream) : allocator_(stream.impl_->stackAllocator_.get())
78
{
79
}
80
81
cv::cuda::Stream::Impl::Impl() : stream(0)
82
{
83
    cudaSafeCall( cudaStreamCreate(&stream) );
84
85
    stackAllocator_ = makePtr<StackAllocator>(stream);
86
}
87
88
cv::cuda::Stream::Impl::Impl(cudaStream_t stream_) : stream(stream_)
89
{
90
    stackAllocator_ = makePtr<StackAllocator>(stream);
91
}
92
93
cv::cuda::Stream::Impl::~Impl()
94
{
95
    stackAllocator_.release();
96
97
    if (stream)
98
        cudaStreamDestroy(stream);
99
}
100
101
cudaStream_t cv::cuda::StreamAccessor::getStream(const Stream& stream)
102
{
103
    return stream.impl_->stream;
104
}
105
106
#endif
107
108
cv::cuda::Stream::Stream()
109
{
110
#ifndef HAVE_CUDA
111
    throw_no_cuda();
112
#else
113
    impl_ = makePtr<Impl>();
114
#endif
115
}
116
117
bool cv::cuda::Stream::queryIfComplete() const
118
{
119
#ifndef HAVE_CUDA
120
    throw_no_cuda();
121
    return false;
122
#else
123
    cudaError_t err = cudaStreamQuery(impl_->stream);
124
125
    if (err == cudaErrorNotReady || err == cudaSuccess)
126
        return err == cudaSuccess;
127
128
    cudaSafeCall(err);
129
    return false;
130
#endif
131
}
132
133
void cv::cuda::Stream::waitForCompletion()
134
{
135
#ifndef HAVE_CUDA
136
    throw_no_cuda();
137
#else
138
    cudaSafeCall( cudaStreamSynchronize(impl_->stream) );
139
#endif
140
}
141
142
void cv::cuda::Stream::waitEvent(const Event& event)
143
{
144
#ifndef HAVE_CUDA
145
    (void) event;
146
    throw_no_cuda();
147
#else
148
    cudaSafeCall( cudaStreamWaitEvent(impl_->stream, EventAccessor::getEvent(event), 0) );
149
#endif
150
}
151
152
#if defined(HAVE_CUDA) && (CUDART_VERSION >= 5000)
153
154
namespace
155
{
156
    struct CallbackData
157
    {
158
        Stream::StreamCallback callback;
159
        void* userData;
160
161
        CallbackData(Stream::StreamCallback callback_, void* userData_) : callback(callback_), userData(userData_) {}
162
    };
163
164
    void CUDART_CB cudaStreamCallback(cudaStream_t, cudaError_t status, void* userData)
165
    {
166
        CallbackData* data = reinterpret_cast<CallbackData*>(userData);
167
        data->callback(static_cast<int>(status), data->userData);
168
        delete data;
169
    }
170
}
171
172
#endif
173
174
void cv::cuda::Stream::enqueueHostCallback(StreamCallback callback, void* userData)
175
{
176
#ifndef HAVE_CUDA
177
    (void) callback;
178
    (void) userData;
179
    throw_no_cuda();
180
#else
181
    #if CUDART_VERSION < 5000
182
        (void) callback;
183
        (void) userData;
184
        CV_Error(cv::Error::StsNotImplemented, "This function requires CUDA 5.0");
185
    #else
186
        CallbackData* data = new CallbackData(callback, userData);
187
188
        cudaSafeCall( cudaStreamAddCallback(impl_->stream, cudaStreamCallback, data, 0) );
189
    #endif
190
#endif
191
}
192
193
namespace 
194
{
195
        bool default_stream_is_initialized;
196
        Mutex mtx;
197
        Ptr<Stream> default_stream;
198
}
199
200
Stream& cv::cuda::Stream::Null()
201
{
202
        AutoLock lock(mtx);
203
        if (!default_stream_is_initialized)
204
        {
205
                default_stream = Ptr<Stream>(new Stream(Ptr<Impl>(new Impl(0))));
206
                default_stream_is_initialized = true;
207
        }
208
        return *default_stream;
209
}
210
211
cv::cuda::Stream::operator bool_type() const
212
{
213
#ifndef HAVE_CUDA
214
    return 0;
215
#else
216
    return (impl_->stream != 0) ? &Stream::this_type_does_not_support_comparisons : 0;
217
#endif
218
}
219
220
221
////////////////////////////////////////////////////////////////
222
// Event
223
224
#ifndef HAVE_CUDA
225
226
class cv::cuda::Event::Impl
227
{
228
public:
229
    Impl(unsigned int)
230
    {
231
        throw_no_cuda();
232
    }
233
};
234
235
#else
236
237
class cv::cuda::Event::Impl
238
{
239
public:
240
    cudaEvent_t event;
241
242
    Impl(unsigned int flags);
243
    ~Impl();
244
};
245
246
cv::cuda::Event::Impl::Impl(unsigned int flags) : event(0)
247
{
248
    cudaSafeCall( cudaEventCreateWithFlags(&event, flags) );
249
}
250
251
cv::cuda::Event::Impl::~Impl()
252
{
253
    if (event)
254
        cudaEventDestroy(event);
255
}
256
257
cudaEvent_t cv::cuda::EventAccessor::getEvent(const Event& event)
258
{
259
    return event.impl_->event;
260
}
261
262
#endif
263
264
cv::cuda::Event::Event(CreateFlags flags)
265
{
266
#ifndef HAVE_CUDA
267
    (void) flags;
268
    throw_no_cuda();
269
#else
270
    impl_ = makePtr<Impl>(flags);
271
#endif
272
}
273
274
void cv::cuda::Event::record(Stream& stream)
275
{
276
#ifndef HAVE_CUDA
277
    (void) stream;
278
    throw_no_cuda();
279
#else
280
    cudaSafeCall( cudaEventRecord(impl_->event, StreamAccessor::getStream(stream)) );
281
#endif
282
}
283
284
bool cv::cuda::Event::queryIfComplete() const
285
{
286
#ifndef HAVE_CUDA
287
    throw_no_cuda();
288
    return false;
289
#else
290
    cudaError_t err = cudaEventQuery(impl_->event);
291
292
    if (err == cudaErrorNotReady || err == cudaSuccess)
293
        return err == cudaSuccess;
294
295
    cudaSafeCall(err);
296
    return false;
297
#endif
298
}
299
300
void cv::cuda::Event::waitForCompletion()
301
{
302
#ifndef HAVE_CUDA
303
    throw_no_cuda();
304
#else
305
    cudaSafeCall( cudaEventSynchronize(impl_->event) );
306
#endif
307
}
308
309
float cv::cuda::Event::elapsedTime(const Event& start, const Event& end)
310
{
311
#ifndef HAVE_CUDA
312
    (void) start;
313
    (void) end;
314
    throw_no_cuda();
315
    return 0.0f;
316
#else
317
    float ms;
318
    cudaSafeCall( cudaEventElapsedTime(&ms, start.impl_->event, end.impl_->event) );
319
    return ms;
320
#endif
321
}