CUDA streams destruction and CudaDeviceReset - c++

I have implemented the following class using CUDA streams
class CudaStreams
{
private:
int nStreams_;
cudaStream_t* streams_;
cudaStream_t active_stream_;
public:
// default constructor
CudaStreams() { }
// streams initialization
void InitStreams(const int nStreams = 1) {
nStreams_ = nStreams;
// allocate and initialize an array of stream handles
streams_ = (cudaStream_t*) malloc(nStreams_*sizeof(cudaStream_t));
for(int i = 0; i < nStreams_; i++) CudaSafeCall(cudaStreamCreate(&(streams_[i])));
active_stream_ = streams_[0];}
// default destructor
~CudaStreams() {
for(int i = 0; i<nStreams_; i++) CudaSafeCall(cudaStreamDestroy(streams_[i])); }
};
If I now run this simple code
void main( int argc, char** argv)
{
streams.InitStreams(1);
streams.~CudaStreams();
cudaDeviceReset();
}
after the cudaDeviceReset() call, I receive the following message:
Unhandled exception 0x772f15de in test.exe: 0x00000000.
What should I do before invoking the destructor to avoid this issue when using cudaDeviceReset()?
EDIT
If I add free(streams_); in the destructor, namely
~CudaStreams() {
for(int i = 0; i<nStreams_; i++) CudaSafeCall(cudaStreamDestroy(streams_[i])); // *
free(streams_); }
I receive the following error message
cudaSafeCall() failed at C:\Users\Documents\Project\Library\CudaStreams.cuh:79 : unknown error
where line 79 is that denoted by * in the destructor.
Furthermore, If I use the same instructions of the constructor and the destructor directly inside the code, namely
void main( int argc, char** argv)
{
int nStreams_ = 3;
cudaStream_t* streams_ = (cudaStream_t*) malloc(nStreams_*sizeof(cudaStream_t));
for(int i = 0; i < nStreams_; i++) CudaSafeCall(cudaStreamCreate(&(streams_[i])));
for(int i = 0; i<nStreams_; i++) CudaSafeCall(cudaStreamDestroy(streams_[i]));
free(streams_);
cudaDeviceReset();
}
everything works well. Perheps is something connected to a bad use of the class?

There are two problems here, both related to the destructor of your class and scope.
Firstly, let's start with a version of your main() which will work correctly:
int main( int argc, char** argv)
{
{
CudaStreams streams;
streams.InitStreams(1);
}
cudaDeviceReset();
return 0;
}
This works correctly because the destructor for streams is called exactly once (when streams falls out of scope), and before cudaDeviceReset is called.
Your original main() (or a compilable version of it, but more about that later...) fails for two reasons. Let's look at it again:
int main( int argc, char** argv)
{
CudaStreams streams;
streams.InitStreams(1);
streams.~CudaStreams();
cudaDeviceReset();
return 0;
}
Here you explicitly call the destructor for streams (which you should almost never do), then cudaDeviceReset, then the destructor is called again at the return statement when streams falls out of scope. The automatic calling the destructor after the context is destroyed is the source of the segfault/exception. The cudaStreamDestroy calls are trying to work on streams without a valid CUDA context. So the solution is not to have any classes which make CUDA API calls fall out of scope (or call their destructors explicitly) when there is no context.
If we made a third version like this:
int main( int argc, char** argv)
{
{
CudaStreams streams;
streams.InitStreams(1);
streams.~CudaStreams();
}
cudaDeviceReset();
return 0;
}
You will get a CUDA runtime error. Because the destructor gets call twice. The first time (explicit) it will work. The second (implict, out of scope) will produce a runtime error: you have a valid context, but are now trying to destroy non-existent streams.
As a final comment/question: How hard would it have been to post and actual compilable version of the code you showed in your original question? It literally required 5 extra lines to make it into a proper repro case someone else could actual compile and run. I find it a bit unreasonable to expect others to make a effort to answer what are basically debugging questions if you are not willing to make a similar effort in providing useful code and information which makes everyone's life that much easier. Think about it. [end of rant]

Related

Clearing stack memory allocated in main()?

I've been calling heap pointers now for as long as I can remember, which in turn has caused me to think about their implications while writing and what I realised was I have no knowledge on how or even if it is possible to clear a stack variable declared within main() from memory once it has been allocated.
Clearly I can just use a struct and destructor or similar, which I would but lets for say I wanted to remove an array that was on the stack declared in main() is it possible?
I wanted to remove an array that was on the stack declared in main()
is it possible?
Yes.
In main() (and most anywhere you use an automatic variable), you can trigger a dtor by closing the containing scope.
Example:
int main(int argc, char* argv[])
{
int retVal = 0;
int arr[10];
T610_t t610;
retVal = t610.exec(argc, argv);
// ...
// ... // t610 exists to end of main() scope.
// ... // arr[10] exists to end of main() scope
return retVal;
}
Instance t610 (of the user defined T610_t type) lasts the life-time of the program, even when not used after the exec() returns retVal;
In contrast:
int main(int argc, char* argv[])
{
int retVal = 0;
{
int arr[10];
T610_t t610;
retVal = t610.exec(argc, argv);
}
// ... // no t610 instance exists, and arr[] is no longer accessible
// ...
// ...
// ...
return retVal;
}
The dtor of instance t610 is called at the close-brace after exec() returns retVal. arr[10] also no longer exists.
All the lines after the close brace do not have access to T610_t, nor arr[10], and any automatic memory grabbed in the 'small scope' is 'released' for re-use. (for instance, another T610_t instance...)
Any 'clearing' of the space used by T610_t is dependent on what the dtor does and what you mean by clearing. Thus, for instance, an array data attribute of T610_t can be filled with 0's (to 'clear' it), and the dtor also releases the memory for re-use. Remember, do no delete when you did no 'new'.
No, you can't really remove a variable out of the current, local scope.
It's not something you should be concerned with - the compiler takes care of everything there.
If you are concerned about privacy, you can of course blank the variable out after use.
A semi-answer to demonstrate a trick the actual answers neglected. (Edit: Neglect changed by the time this was posted)
If you have a large block of memory that you allocated on the stack (an Automatic allocation) and you need that memory back without returning from the function, you can introduce a new scope by calling another function
int get_and_compute()
{
int array[1024*1024];
read_in_a_lot_of_inputs(array);
return compute_stuff_with__array(array);
}
int main()
{
int result = get_and_compute();
// now you have enough memory to call
job_that_takes_a_lot_of_RAM(result);
}
Or by surrounding the code in question with a set of braces
int main()
{
int result = 0;
{ //introduce a new scope
int array[1024*1024];
read_in_a_lot_of_inputs(array);
result = compute_stuff_with__array(array);
} // array goes out of scope here
// now you have enough memory to call
job_that_takes_a_lot_of_RAM(result);
}
Most of the time I prefer option 1, adding a function, but there are times where the extra function doesn't make much sense. Pick the option that is easiest to read, write, and maintain.
I wanted to remove an array that was on the stack declared in main() is it possible?
Simply let the execution go out of the scope where the automatic variable is declared:
int main() {
{
int arr[10];
}
// arr is destroyed, and further local variables can reuse its memory
}

Access command line arguments in C++

Is it possible to get the command line arguments without receiving them via int main(int, char**)? I don't want to pass the arguments to multiple methods, so a global function would be perfect. Also, I do not want to store the arguments by myself via global variables. I'm running Windows and Linux.
edit:
Example:
int main()
{
int argc = GetArgumentCount();
char ** argv = GetArguments();
return 0;
}
edit:
It's possible to use LPTSTR WINAPI GetCommandLine(void); in win32.
https://msdn.microsoft.com/en-us/library/ms683156(v=vs.85).aspx
I'm looking for equivalent functions in Linux.
Is it possible to get the command line arguments without receiving
them via int main(int, char**)?
Yes, with platform-specific functions. But that's not necessary (see below).
I don't want to pass the arguments to multiple methods,
That's understandable. It's an anti-pattern also known as "tramp data".
Also, I do not want to store the arguments by myself via global variables.
Yes, global variables are rarely a good idea.
Here's an alternative approach: store them as a static local container object in some globally available non-member function which returns the container by reference.
Example:
#include <iostream>
#include <string>
#include <vector>
std::vector<std::string>& Arguments()
{
static std::vector<std::string> arguments;
return arguments;
}
void f()
{
// use arguments anywhere else:
std::cout << Arguments()[0];
}
int main(int argc, char* argv[])
{
for (int i = 0; i < argc; ++i)
{
Arguments().push_back(argv[i]);
}
f();
}
Of course, this can be made more sophisticated. For example, you might want to prevent anyone else but main from changing the vector by wrapping the vector in a class and declaring main as a friend, something like this:
#include <iostream>
#include <string>
#include <vector>
class Arguments final
{
public:
static int Count()
{
return arguments.size();
}
static std::string Get(int index)
{
return arguments[index];
};
private:
Arguments() = delete;
friend int main(int argc, char* argv[]);
static std::vector<std::string> arguments;
};
std::vector<std::string> Arguments::arguments;
void f()
{
// use Arguments anywhere else:
std::cout << Arguments::Get(0);
}
int main(int argc, char* argv[])
{
for (int i = 0; i < argc; ++i)
{
Arguments::arguments.push_back(argv[i]);
}
f();
}
Note that special care is needed to avoid bugs at program shutdown, when static objects are destroyed. You must make sure that no destructor of a static object accesses Arguments, or else you risk undefined behaviour.
Is it possible to get the command line arguments without receiving them via int main(int, char**) ?
No (at least, not in portable manner), however you could put the usual argc, argv into some global variable (or other global data, often after parsing). And that could also be into some static data with other functions in the same translation unit retrieving it. Hence a reasonable (readable and portable) approach would be:
static int myargc;
static char **myargv;
int GetArgumentCount(void) {
return myargc;
}
char**GetArguments(void) {
return myargv;
}
int main(int argc, char**argv) {
myargc= argc;
myargv= argv;
/// etc....
Notice that on some systems or some implementations you might access to the command line arguments in some other ways.
dirty Linux specific tricks
For example, on Linux, using proc(5), you might parse /proc/self/cmdline but it is unreasonable to do that (on your Linux system, try to run od -cx /proc/self/cmdline in your terminal to guess what I mean), so I still recommend using int main(int argc, char**argv) and storing, in some global or static data, the argc and argv, or more probably, do some parsing of program arguments.
So on Linux, you might code your GetArgumentCount and GetArguments functions (by parsing /proc/self/cmdline, see also this) but it would be foolish to do so without using argc and argv from main (even if it is technically doable). Coding such a crazy GetArgumentCount and GetArguments which parses /proc/self/cmdline is left as an exercise to the masochistic reader.
Perhaps you need that because some static data's constructor -running before main and called before it from crt0- uses them; but in that case, your program's design is IMHO very wrong. I have no idea if similar dirty tricks are doable in Windows.
If you really think that is a good idea, you can easily make cor command line arguments global:
int argc_ = 0;
char** argv_ = NULL;
int main(int argc, char* argv[]) {
argc_ = argc;
argv_ = argv;
// ...
}

Virtual move constructor in C++

Just faced with a situation and don't know what to do... Here is the code I have right now:
class IMyDbAccessor {
public:
int getSum(); // quite important for my case that it is not const.
// it does some caching. Of course I may use mutable,
// but actually it is not that important here.
};
void SomeBusinessLogic(IMyDbAccessor& dbacc) { /* implementation */ }
int main(int argc, char** argv) {
MyDbAccessor acc(argv);
SomeBusinessLogic(acc);
}
I don't like it, because it is not expressive enough. I would like to have
void SomeBusinessLogic(IMyDbAccessor&& dbacc) { /* implementation */ }
to show that SomeBusinessLogic wants to own a passed object, so main should look like
int main(int argc, char** argv) {
MyDbAccessor acc(argv);
SomeBusinessLogic(std::move(acc));
}
But of course it is impossible... Does anyone know what was a reasoning for that? For me it makes a perfect sense.
Or my feelings are wrong and I should not make SomeBusinessLogic responsible for IMyDbAccessor ownership, so it's better to pass it as a const IMyDbAccessor&?
I don't like it, because it is not expressive enough.
Looks plenty expressive to me. Passing an object by reference means the function can operate on an existing object provided by the caller, not on a copy. No worries about managing ownership.
I would like to have
void SomeBusinessLogic(IMyDbAccessor&& dbacc) { /* implementation */ }
to show that SomeBusinessLogic wants to own a passed object
That is not what an rvalue reference represents. An rvalue reference means that dbacc will refer to either a temporary object created by the compiler at the actual call site, or a pre-existing object that the caller passes with std::move(). Either way, the object that dbacc refers to is expected not to be used anymore after SomeBusinessLogic() exits, so SomeBuinessLogic() is allowed to "steal" ownership of any internal data held by the object that dbacc refers to, instead of make copies of it. This has nothing to do with ownership of the object itself. That still lies strictly with the caller.
so main should look like
int main(int argc, char** argv) {
MyDbAccessor acc(argv);
SomeBusinessLogic(std::move(acc));
}
But of course it is impossible...
What you are looking for is std::unique_ptr:
void SomeBusinessLogic(std:::unique_ptr<IMyDbAccessor> dbacc) { /* implementation */ }
int main(int argc, char** argv) {
std::unique_ptr<IMyDbAccessor> acc(new MyDbAccessor(argv));
SomeBusinessLogic(std::move(acc));
}
Or:
int main(int argc, char** argv) {
SomeBusinessLogic(std::make_unique<MyDbAccessor>(argv));
}
Only one std::unique_ptr at a time should ever hold a given pointer, as std::unique_ptr frees the memory being pointed at when destructed. That is what makes it "unique". When you see a std::unique_ptr, you know who the owner is. And passing a std::unique_ptr object by value to a function means it exists only for the lifetime of the function.
So, this approach makes it very clear that dbacc itself, not the caller, holds exclusive ownership of the IMyDbAccessor object, and will free that object when SomeBusinessLogic() exits (unless SomeBusinessLogic() decides to std::move() dbacc to another std::unique_ptr that is outside of SomeBusinessLogic()).
Or my feelings are wrong and I should not make SomeBusinessLogic responsible for IMyDbAccessor ownership, so it's better to pass it as a const IMyDbAccessor&?
I would, yes. Unless there is some compelling reason that SomeBusinessLogic() must take ownership away from the caller.
I think the type you are looking for is probably void SomeBusinessLogic(std::unique_ptr<IMyDbAccessor>)?
Indicates ownership is being transferred, and accepts derived objects
Do SomeBusinessLogic(std::forward(acc)).
For example:
#include <iostream>
#include <utility>
class IMyDbAccessor {
public:
virtual int getSum() = 0;
};
class MyDbAccessor : public IMyDbAccessor {
public:
virtual int getSum() { return 0; }
};
void SomeBusinessLogic(IMyDbAccessor&& dbacc) { std::cout << dbacc.getSum() << std::endl; }
int main(int argc, char** argv) {
MyDbAccessor acc;
SomeBusinessLogic(std::forward<MyDbAccessor>(acc));
}
Try it here:
http://cpp.sh/7pbrm
If you are looking for a way to give feedback "Hey I will modify this variable!" at the call location, I strongly recommend const pointers.
Then you have:
void SomeBusinessLogic(IMyDbAccessor* const dbacc) { /* implementation */ }
and
int main(int argc, char** argv) {
MyDbAccessor acc;
SomeBusinessLogic(&acc);
}

Is it safe to modify an argument from in a slot function in Qt?

I have a signal that emits a std::vector<uint8_t> which contains a load of data (a buffer).
Then in the receiving objects I have a slot that takes an argument std::vector<uint8_t> data
Then I try to decode this data. One of the things I have to do is remove padding, for example:
void receive_slot(std::vector<uint8_t> data)
{
// Remove padding
if (data.size() > 20)
data.resize(data.size() - 20);
}
Now, I thought that this argument passed in is a copy that I can "do what I want with". However, doing a re-size of larger then ~10 bytes crashes my program. I assume that re-sizing less then ~10 bytes does not crash it only by luck.
I therefore assume that I can't safely do this and should first copy it to a new data buffer.
Can anyone enlighten me regarding this?
To provide a direct anwser to the question:
Slots in Qt are just normal function calls (when and with which arguments they're called is the difference, managed by Qt), and it's perfectly valid to modify function arguments (when non-const obviously). You're right when you say that you're given a copy and that you can do "do what you want with it".
In this case, the error doesn't purely come from the fact that you're modifying the function argument.
The code you show is perfectly valid and safe and the problem is elsewhere in your code. Something else is corrupting the memory, and the crash happens in receive_slot by pure chance. It's really easy to verify that: you should have put together the minimal test case below before even asking your question on SO.
Works for me.
#include <vector>
#include <QObject>
#include <QCoreApplication>
#include <QAtomicInt>
QAtomicInt n = 0;
class Object : public QObject {
Q_OBJECT
public:
Q_SIGNAL void source(const std::vector<uint8_t> &);
Q_SLOT void sink(std::vector<uint8_t> data) {
// Remove padding
if (data.size() > 20)
data.resize(data.size() - 20);
n.fetchAndAddOrdered(1);
}
};
Q_DECLARE_METATYPE(std::vector<uint8_t>)
int main(int argc, char ** argv)
{
QCoreApplication a(argc, argv);
qRegisterMetaType<std::vector<uint8_t> >();
Object src, dstD, dstQ;
const int N = 1000000;
// note elision of const & from the parameter types
dstD.connect(&src, SIGNAL(source(std::vector<uint8_t>)),
SLOT(sink(std::vector<uint8_t>)));
dstQ.connect(&src, SIGNAL(source(std::vector<uint8_t>)),
SLOT(sink(std::vector<uint8_t>)), Qt::QueuedConnection);
for (int i = 0; i < N; ++i) {
std::vector<uint8_t> v;
v.resize(qrand() % 100);
emit src.source(v);
}
a.processEvents();
Q_ASSERT(n.loadAcquire() == (2*N));
return 0;
}
#include "main.moc"

Constructor of class of an array

i am getting error in this code
class business
{
public:
business(); // Default Constructor
business(string busines,int r)
{
busines=busines;
ratings=r;
} // constructor;
private:
string busines;
int ratings;
int items_owned;
int business_cancellation;
int biz_size_of_building;
int biz_shipping_method;
};
int main(int argc, char *argv[])
{
business b[10];
b[b_count](busines,rating);
return 0;
}
It gives me the following error (http://ideone.com/FfajNS):
prog.cpp: In function β€˜int main(int, char**)’:
prog.cpp:32:32: error: no match for call to β€˜(business) (std::string&, int&)’
You're attempting to call a constructor on an already constructed object ... the default constructor was called during the array creation, therefore you cannot "construct" the object again. For your application, you may want to look into using a std::vector where you can create a array-like container using an object initialized from a set of default arguments.
For instance, you could do:
std::vector<business> array(10, business(business_string, rating));
I believe you want something like this:
b[2] = business("Denny's", 50);
This creates a temporary business variable by calling the constructor with the given parameters. The temporary is then copied into slot 3 of the array b.
The array b already created 10 business objects using the default constructor of that class. You can access those objects by business someBusiness = b[someIndex];
edit:
If you want to set the values of your individual objects, simply do this (notice, that you don't create these objects, just set their values):
for(int i=0; i<10; i++)
{
b[i].busines = ...;
b[i].ratings = ...;
/* or to create new ones */
b[i] = business("asd", 10);
}
It would be even better, if you stored these objects in vector, like Jason suggested
business b[10];
You create 10 "default" business object. What is b_count? I hope some int from 0 to 9.
But here you are "calling" a business object with 2 arguments:
b[b_count](busines,rating);
But business have no operator()() defined with 2 parametr.
EDIT:
You definitely have to use std::vector and carefully read the other answers.
But I know that on occasion beginners are not allowed to use the STL library, and anyway it seems that you should understand how constructors are used and how the elements of an array are initialized. Please read about static members and how they are defined and try to understand how the following example works.
#include <string>
using std::string;
class business
{
public:
business() // Default Constructor
:busines(def_busines),ratings(def_ratings){};
business(const string& bus,int r) // constructor;
:busines(bus),ratings(r){}
static void SetDef(const string& busines,int r)
{
def_busines=busines;
def_ratings=r;
}
private:
string busines;
int ratings;
static string def_busines;
static int def_ratings;
int items_owned;
int business_cancellation;
int biz_size_of_building;
int biz_shipping_method;
};
string business::def_busines=""; // Set here the default-defaults
int business::def_ratings=1;
int main(int argc, char *argv[])
{
business::SetDef("Some business",2);
business a[10];
business::SetDef("Other business",3);
business b[10];
business c("Third business",4);
return 0;
}