iterating over a doubly linked list from device - c++

I need to create a doubly linked list on a cuda device.
I have the host code:
class Foo
{
public:
int my_index;
static int count;
static int index;
static Foo* first;
static Foo* last;
Foo* next;
Foo* prev;
Foo(); //adds object to list
~Foo(); //deletes object from list
}
Foo* Foo::first = 0;
Foo* Foo::last = 0;
int Foo::count = 0;
int Foo::index = 0;
when i want to iterate through it:
for (Foo* pr = Foo::first; pr; pr = pr->next)
{
//do something
}
My first problem is:
there are several other classes that inherit from Foo
and they have differrent sizes, so how can I:
either copy all
created classes of type Foo and all derived classes to the device
or even better, completely store the whole linked list from Foo on the device
I dont have to access the data from Foo on the host,
I need it only on the device.
My second problem:
I have multiple CUDA devices (3 CUDA capable graphic cards)
how could i access the device doubly linked list on both devices?
peer-to-peer copy?
something else?

I'm not familiar with CUDA, but it sounds you need to transform each object into some form so that it can be transferred to the device, and the problem is that the objects are different sizes and have different contents. If so, you should be able to solve the problem with a virtual function that transforms each object into a form that can be transferred according to its type. For example, if you were transferring data as binary using a void * buffer, it might look like:
class Foo
{
public:
// ... Everything else ...
virtual void *add_transfer_data(void *buffer)
{
// Copy whatever makes sense for a Foo object into the buffer.
memcpy(buffer, [something], n);
return reinterpret_cast<unsigned char *>(buffer) + n;
}
};
class Bar: public Foo
{
public:
// ... Everything else ...
virtual void *add_transfer_data(void *buffer)
{
// First, take care of the Foo part of the object.
buffer = Foo::add_transfer_data(buffer, buffer_size);
// Now copy whatever else a Bar object needs into the buffer.
memcpy(buffer, [something], m);
return reinterpret_cast<unsigned char *>(buffer) + m;
}
};
void transfer_data(void *buffer)
{
void *next_location = buffer;
for (Foo* pr = Foo::first; pr; pr = pr->next)
{
next_location = pr->add_transfer_data(next_location);
}
// Send the contents of buffer to the device somehow.
}
Of course, your versions of add_transfer_data might be very different depending on the details of how the transfer works and what the objects look like. There might be nothing to write for just a plain Foo object, for example. Hopefully, though, this illustrates the central idea.

I don't know anything about CUDA, so there is likely a better answer.
If your problem is determining the size of an instance of Foo, then why not give the class a virtual size method?
// In Foo:
virtual size_t size() const;
// In class T, a derivation of Foo:
size_t size() const override { return sizeof(T); }

Related

How to make a temporary variable's pointer valid in the future?

I have a project, which receives data from a socket, then handles it and saves good data into a container.
I want high performance, so, i need to keep the copy operation less as i can.
here is my first code:
struct Data { // here is a demo, in real project, Data is a large struct
int a;
char b[20];
}; // data type
std::vector<const Data*> data_base;
void Handle(const Data& a) {
if (a.good()) { // only few data will get good
data_base.emplace_back(&a); // data_map saved pointer to avoid copy
}
}
int main() {
while(true) {
Data* a = new Data;// here waste memory, since only few data need to be saved
socket.Recv(*a);
Handle(*a);
}
}
in this code, I saved data's pointer, so, the copy cost is saved.
But the problem is I new a lot of objects, which spends a lot of memory.
I have second design like this:
struct Data {
int a;
char b[20];
}; // data type
std::vector<const Data*> data_base;
void Handle(const Data& a) {
if (a.good()) { // only few data will get good
// TODO: copy a's value to a permanent pointer, i don't know how to do that
}
}
int main() {
Data a;
while(true) {
socket.Recv(a); // make a reusable
Handle(*a);
}
}
I think the second solution can save memory, and the performance wont be harmed. (no additional copy), am i right?
And how can I copy a temp variable into a pointer container(see TODO in solution 2)?
Don't do any of that.
Do this instead:
struct Data {
int a;
char b[20];
}; // data type
std::vector<Data> data_base;
void Handle(const Data& a) {
if (a.good()) { // only few data will get good
data_base.push_back(a);
}
}
int main() {
Data a;
while(true) {
socket.Recv(a);
Handle(a);
}
}
Copying your Data struct seems to be pretty trivial, and in any case you've stated that it will only happen rarely anyway. So the right thing to do is to optimize for the common case. Reuse the space for the data for receiving, and make a copy only when you need it.
// TODO: copy a's value to a permant pointer, i dont know how to do that
You could do, it's just:
data_base.push_back(new Data(a))
But your code leaks memory. Use smart pointers:
std::vector<std::unique_ptr<Data>> data_base;
Anyway, I believe the intention is not to copy the data, but copy only pointers and only when needed. Use smart pointers anyway. I believe something along:
struct Data { int tmp; bool good(); };
std::vector<std::unique_ptr<Data>> data_base;
void socket_recv(std::unique_ptr<A>& a);
void handle(std::unique_ptr<Data>& a) {
if (a->good()) { // only few data will get good
data_base.emplace_back(std::move(a)); // we move the pointer around
a = std::make_unique<Data>(); // allocate new memory for next run
}
}
int main() {
std::unique_ptr<Data> a = std::make_unique<Data>();
while(true) {
socket_recv(a); // make a reusable
handle(a);
}
}
or using raw pointers:
std::vector<Data *> data_base;
void socket_recv(Data* a);
void handle(Data*& a) {
if (a->good()) { // only few data will get good
data_base.push_back(a); // we move the pointer around
a = new Data(); // allocate new memory for next run
}
}
int main() {
A *a = new Data();
while(true) {
socket_recv(a); // make a reusable
handle(a);
}
delete a;
}

Impossible to store cocos2d::Animation * in a std::vector of structure?

I work on a project made with cocos2d-x framework (c++).
In my Player class, I have to manage the animations.
Iinitially I had this code that worked without any problem:
First, the animation object is a cocos2d Class cocos2d::Animation. Just remember that this object contains a cocos2d::Vector<AnimationFrame*> _frames; member.
Doc: http://www.cocos2d-x.org/reference/native-cpp/V3.5/d3/dc5/classcocos2d_1_1_animation.html#a0fdc0be158df7e09d04644be353db056
class Player : public cocos2d::Sprite {
private:
cocos2d::Map<std::string, cocos2d::Animation*> animations;
cocos2d::Vector<cocos2d::SpriteFrame*> getAnimation(const char *format, int frameStart, int count);
void update(float delta) override;
bool init() override;
public:
static Player* create();
bool init() override;
//...
};
And the implementation side:
bool Player::init() {
//...
animations.insert("idleN", Animation::createWithSpriteFrames(getAnimation("%04d", 207, 9), 0.1));
//...
}
Vector<SpriteFrame*> Player::getAnimation(const char *format, int frameStart, int count) {
auto spriteCache = SpriteFrameCache::getInstance();
Vector<SpriteFrame*> animFrames;
char str[100] = {0};
for (int i = 1; i <= count; i++)
{
sprintf(str, format, frameStart);
log("%s", str);
animFrames.pushBack(spriteCache->getSpriteFrameByName(str));
frameStart++;
}
return animFrames;
}
//later in the code execution
void Player::manageIdle() {
auto idleAnim = Animate::create(animations[0].anim);
runAction(idleAnim);
}
You can see each Animation is contained in cocos2d::Map<std::string, cocos2d::Animation*> and as I say before, this code worked perfectly, no error.
But I needed some more informations in addition to the name and the object itself so I decided to use a structure to store all infos for each animation. And I replaced the cocos2d::Map<std::string, cocos2d::Animation*> by std::vector<animData> with animData as structure. I refactored the code like so:
class Player : public cocos2d::Sprite {
public:
typedef struct animation {
std::string name;
cocos2d::Animation* anim;
//all others info needed, not relevant here, (just several enum type variables)
} animData;
private:
std::vector<animData > animations; //the new container
//rest of code stay unchanged
};
The changes in the implementation side:
bool Player::init() {
//...
animations.push_back({"idleN", Animation::createWithSpriteFrames(getAnimation("%04d", 207, 9), 0.1)});
//no problem here...
}
But now, when I try to create a new anim with a animation saved in my container (vector) I get a SegV on this line:
void Player::manageIdle() {
auto idleAnim = Animate::create(animations[0].anim); //SegV here, in Animate::create() funct
runAction(idleAnim);
}
After search, I find that each structure member anim which is type of cocos2d::Animation*, now conatains a empty cocos2d::Vector<AnimationFrame*> _frames; and there is the problem !
It’s as if they lose the cocos2d::Vector<AnimationFrame*> ref or something like that.
So my question is why cocos2d::Vector<AnimationFrame*> become empty with my refactored code and not whith the previous one ?
I found this with test like that:
auto test = animList[0].anim->getFrames();
if (test.empty()) {
log("empty"); //The test output empty
}
Debugguer screen in the end of the init() funct:
Debugguer screen in Player::manageIdle() funct:
Edit: when I add animations.back().anim->retain(); right after the line to add an element in the vector, it solves the problem !
animations.push_back({"idleN", Animation::createWithSpriteFrames(getAnimation("%04d", 207, 9), 0.1)});
animations.back().anim->retain();
Because cocos2d::Animation* inherit from cocos2d::Ref, it is an auto-release object. When used inside a cocos2d container like cocos2d::Map or cocos2d::Vector, it is auto managed by the container itself. But I use a std::vector so I lose the ref I think. Something like that.
Now I need to find a way to get rid of this additional line of code because this multiple by twice my number of line here !
So new question here: How I can get rid of the fact I have to call animations.back().anim->retain(); each time I add a new element in my vector ?
You might create a wrapper around Ref, which "retains" ownership, and store this wrapper instead, sort of a std::unique_ptr e.g.
template<typename T> class RefOwner {
public:
RefOwner(T *t) : ref(t) {
ref->retain();
}
~RefOwner() {
ref->release();
}
T *operator->() { return ref; }
private:
T *ref;
};
and then use it as
struct animData {
std::string name;
RefOwner<cocos2d::Animation> anim;
//all others info needed, not relevant here, (just several enum type variables)
};
Disclaimer: I have no experience with cocos2d-x, just looked at Animation and Ref

How can I mimic Java's class zeroing in C++?

In C, in order to assure that all structs are zeroed I wrap malloc with:
void* safe_malloc(size_t size){
void *result = malloc(size);
memset(result, 0, size); //NULL check ommitted for brevity
return result;
}
so that I can avoid doing:
struct Foo {
int bar;
int bat;
};
struct Foo *tmp = malloc(sizeof(struct Foo));
tmp->bar = 0;
tmp->bat = 0; // I want to avoid this laundry list of initializers
I want to do something similar for C++ whereby I want all members of a class to be initialized to zero like what is done automatically in Java. There are two problems that come to mind using a solution like the C solution: 1. you cant clear the vtable ptr and 2. a subclass will clear inherited member values.
class Foo {
public:
int bar;
int bat;
Foo(int bar){
this->bar = bar;
this->bat = 0; // I dont want to explicitly have to initialize this here
}
}
class Baz : public Foo {
public:
int bam;
Baz(int bar, int bam) : Foo(bar) {
this->bam = bam;
}
}
How can I avoid the laundry list equivalent in C++?
Prefer calloc over malloc + memset
To zero the objects, choose your constructors wisely.
You can overload new operator to return zeroed memory. (Overload new for a class or globally as per your requirement) This overloaded new should zero the bytes allocated.

Knowing when to delete associated user data from a std::map<void *, ...>

I have a map of addresses that allows me to store arbitrary data with objects. Basically, a library I'm writing has a templated function that winds up storing arbitrary data with objects.
std::map<void *, MyUserData>
This works, until the object passed in is destroyed, leaving its user data in the map. I want the associated user data to be removed as well, so I need to somehow listen for the destructor of the passed in object,
Some example code that illustrates the problem:
#include <map>
#include <memory>
struct MyUserData
{
int someNum;
};
std::map<void *, MyUserData> myMap;
template <typename T>
registerObject<T>(const std::shared_ptr<T> & _object)
{
static inc = 0;
myMap[(void *)&_object->get()].someNum = inc++;
}
struct MyObject
{
int asdf;
};
int main(int _argc, char ** _argv)
{
auto obj = std::make_shared<MyObject>();
obj->asdf = 5;
registerObject(obj);
obj = 0;
//The user data is still there. I want it to be removed at this point.
}
My current solution is to set a custom deleter on the shared_ptr. This signals me for when the object's destructor is called, and tells me when to remove the associated user data. Unfortunately, this requires my library to create the shared_ptr, as there is no "set_deleter" function. It must be initialized in the constructor.
mylib::make_shared<T>(); //Annoying!
I could also have the user manually remove their objects:
mylib::unregister<T>(); //Equally annoying!
My goal is to be able to lazily add objects without any prior-registration.
In a grand summary, I want to detect when the object is deleted, and know when to remove its counterpart from the std::map.
Any suggestions?
P.S. Should I even worry about leaving the user data in the map? What are the chances that an object is allocated with the same address as a previously deleted object? (It would end up receiving the same user data as far as my lib is concerned.)
EDIT: I don't think I expressed my problem very well initially. Rewritten.
From you code example, it looks like the external interface is
template <typename T>
registerObject<T>(const std::shared_ptr<T> & _object);
I assume there is a get-style API somewhere. Let's call this getRegisteredData. (It could be internal.)
Within the confines of the question, I'd use std::weak_ptr<void> instead of void*, as std::weak_ptr<T> can tell when there are no more "strong references" to the object around, but won't prevent the object from being deleted by maintaining a reference.
std::map<std::weak_ptr<void>, MyUserData> myMap;
template <typename T>
registerObject<T>(const std::shared_ptr<T> & _object)
{
static inc = 0;
Internal_RemoveDeadObjects();
myMap[std::weak_ptr<void>(_object)].someNum = inc++;
}
template <typename T>
MyUserData getRegisteredData(const std::shared_ptr<T> & _object)
{
Internal_RemoveDeadObjects();
return myMap[std::weak_ptr<void>(_object)];
}
void Internal_RemoveDeadObjects()
{
auto iter = myMap.cbegin();
while (iter != myMap.cend())
{
auto& weakPtr = (*iter).first;
const bool needsRemoval = !(weakPtr.expired());
if (needsRemoval)
{
auto itemToRemove = iter;
++iter;
myMap.erase(itemToRemove);
}
else
{
++iter;
}
}
}
Basically, std::weak_ptr and std::shared_ptr collaborate and std::weak_ptr can detect when there are no more std::shared_ptr references to the object in question. Once that is the case, we can remove the ancillary data from myMap. I'm using the two interfaces to myMap, your registerObject and my getRegisteredData as convenient places to call Internal_RemoveDeadObjects to perform the clean up.
Yes, this walks the entirety of myMap every time a new object is registered or the registered data is requested. Modify as you see fit or try a different design.
You ask "Should I even worry about leaving the user data in the map? What are the chances that an object is allocated with the same address as a previously deleted object?" In my experience, decidedly non-zero, so don't do this. :-)
I'd add a deregister method, and make the user deregister their objects. With the interface as given, where you're stripping the type away, I can't see a way to check for the ref-count, and C++ doesn't provide a way to check whether memory has been deleted or not.
I thought about it for a while and this is as far as I got:
#include <memory>
#include <map>
#include <iostream>
#include <cassert>
using namespace std;
struct MyUserData
{
int someNum;
};
map<void *, MyUserData> myMap;
template<class T>
class my_shared_ptr : public shared_ptr<T>
{
public:
my_shared_ptr() { }
my_shared_ptr(const shared_ptr<T>& s) : shared_ptr<T>(s) { }
my_shared_ptr(T* t) : shared_ptr<T>(t) { }
~my_shared_ptr()
{
if (unique())
{
myMap.erase(get());
}
}
};
template <typename T>
void registerObject(const my_shared_ptr<T> & _object)
{
static int inc = 0;
myMap[(void *)_object.get()].someNum = inc++;
}
struct MyObject
{
int asdf;
};
int main()
{
{
my_shared_ptr<MyObject> obj2;
{
my_shared_ptr<MyObject> obj = make_shared<MyObject>();
obj->asdf = 5;
registerObject(obj);
obj2 = obj;
assert(myMap.size() == 1);
}
/* obj is destroyed, but obj2 still points to the data */
assert(myMap.size() == 1);
}
/* obj2 is destroyed, nobody points to the data */
assert(myMap.size() == 0);
}
Note however that it wouldn't work if you wrote obj = nullptr; , or obj.reset(), since the object isn't destroyed in those cases (no destructor called). Also, you can't use auto with this solution.
Also, be careful not to call (void *)&_object.get() like you were doing. If I'm not terribly wrong, by that statement you're actually taking the address of the temporary that _object.get() returns, and casting it to void. That address, however, becomes invalid instantly after.
This sounds like a job for... boost::intrusive (http://www.boost.org/doc/libs/1_53_0/doc/html/intrusive.html)! I don't think the current interface will work exactly as it stands though. I'll try to work out a few more details a little later as I get a chance.
You can just do
map.erase(map.find(obj));
delete obj;
obj = 0;
this will call the destructor for your user data and remove it from the map.
Or you could make your own manager:
class Pointer;
extern std::map<Pointer,UserData> data;
class Pointer
{
private:
void * pointer;
public:
//operator ()
void * operator()()
{
return pointer;
}
//operator =
Pointer& operator= (void * ptr)
{
if(ptr == 0)
{
data.erase(data.find(pointer));
pointer = 0;
}
else
pointer = ptr;
return *this;
}
Pointer(void * ptr)
{
pointer = ptr;
}
Pointer()
{
pointer = 0;
}
~Pointer(){}
};
struct UserData
{
static int whatever;
UserData(){}
};
std::map<Pointer,UserData> data;
int main()
{
data[Pointer(new UserData())].whatever++;
data[Pointer(new UserData())].whatever++;
data[Pointer(new UserData())].whatever++;
data[Pointer(new UserData())].whatever++;
Pointer x(new UserData());
data[x].whatever;
x = 0;
return 0;
}

Beginner and C++ templates: Is it an how possible using C++ template make a class oriented to work with chars work with costume structures?

So I am quite wary new to C++ and I really do not understand templates and how to use tham thow I rad wikipedia and started reading like 2000 pages long book on C++... So I am probably way 2 impatient but I wonder If using C++ templates we can make for example such simple class pair work with costume structures instead of chars.
#include <iostream>
#include <vector>
// Boost
#include <boost/thread.hpp>
#ifndef _IGraphElementBase_h_
#define _IGraphElementBase_h_
#pragma once
using namespace std ;
class IGraphElementBase {
public:
boost::thread GraphWorker;
mutable boost::mutex GraphItemMutex;
boost::condition_variable GraphItemMutexConditionVariable;
int SleepTime;
// Function for preparing class to work
virtual void Init(){ SetSleepTime(1);}
void SetSleepTime(int timeMS)
{
SleepTime = timeMS;
}
// Function for data update // word virtual makes it possible to overwrite it
virtual void updateData(){}
void StartThread()
{
GraphWorker = boost::thread(&IGraphElementBase::Call, this);
}
virtual void CleanAPI(){}
virtual void Clean()
{
GraphWorker.interrupt();
GraphWorker.join();
CleanAPI();
}
virtual void CastData(){}
//Here is a main class thread function in infinite loop it calls for updateData function
void Call()
{
try
{
for(;;){
boost::this_thread::sleep(boost::posix_time::milliseconds(SleepTime));
boost::mutex::scoped_lock lock(GraphItemMutex);
boost::this_thread::interruption_point() ;
updateData();
lock.unlock();
CastData();
GraphItemMutexConditionVariable.notify_one();
}
}
catch (boost::thread_interrupted)
{
// Thread end
}
}
};
#endif // _IGraphElementBase_h_
#include "IGraphElementBase.h"
#ifndef _IGraphElement_h_
#define _IGraphElement_h_
using namespace std ;
class IGraphElement : public IGraphElementBase{
// We should define prototype of functions that will be subscribers to our data
typedef void FuncCharPtr(char*, int) ;
public:
struct GetResultStructure
{
int length;
char* ptr;
};
// initGet sets up a pointer holding a copy of pointer of data we want to return on Get() call
void InitGet(char * pointerToUseInGetOperations, int pointerToUseInGetOperationsSize)
{
pointerToGet = pointerToUseInGetOperations;
pointerToGetSize = pointerToUseInGetOperationsSize;
}
// Function for adding subscribers functions
void Add(FuncCharPtr* f)
{
FuncVec.push_back(f);
}
// Returns pointer to copy of current graphItem processed data
GetResultStructure Get()
{
boost::mutex::scoped_lock lock(GraphItemMutex);
char * dataCopy = new char[pointerToGetSize];
memcpy (dataCopy,pointerToGet,pointerToGetSize);
lock.unlock();
GraphItemMutexConditionVariable.notify_one();
GetResultStructure result;
result.ptr = dataCopy;
result.length = pointerToGetSize;
return result;
}
void Clean()
{
GraphWorker.interrupt();
GraphWorker.join();
CleanAPI();
//delete[] pointerToGet;
//pointerToGet = 0;
}
// Cast data to subscribers and clean up given pointer
void CastData(){
for (size_t i = 0 ; i < FuncVec.size() ; i++){
char * dataCopy = new char[pointerToGetSize];
memcpy (dataCopy,pointerToGet,pointerToGetSize);
FuncVec[i] (dataCopy, pointerToGetSize) ;}
}
// Cast given data to subscribers and clean up given pointer
void CastData(char * data, int length){
for(size_t i = 0 ; i < FuncVec.size(); i++){
char* dataCopy = new char[length];
memcpy(dataCopy, data, length);
FuncVec[i](dataCopy, length);
}
}
private:
// Char pointer to hold a copy of pointer of data we want to return on Get() call
char* pointerToGet;
int pointerToGetSize;
// Vector to hold subscribed functions
vector<FuncCharPtr*> FuncVec ;
};
#endif // _IGraphElement_h_
So what is most intresting for me in that classes in short:
- typedef void FuncCharPtr(char*, int) ;
- vector<FuncCharPtr*> FuncVec ;
- functions like void CastData(char * data, int length)
It is really wary intresting for me if it is possile to somehow using templates make my classes work with costume structures. So Is it possible and how to do such thing?
Templates are a parameterization of a class. That is, instead of having a bunch of different classes such as
class myclass_int
{
int x;
}
class myclass_double
{
double x;
}
etc...
if you can see the pattern, the only thing different is the type used, SO, we will use an abstract type called a template as a sort of place holder,
class myclass_T
{
T x;
}
THIS CLASS IS NOT A SINGLE CLASS BUT A WHOLE COLLECTION. If we replace T with int we get the first class and T with double we get the second.
But when we instantiate myclass_T we must then specify what T actually is(is it in an int, double, etc..)?
so we will define this parameterized class as
template <typename T>
class myclass
{
T x;
}
And use T as it we already new what it really was.
That one class represents all the possible classes you could make up that had specific types used(I gave 2 instances at the start).
Templates simply make it easier to define such classes. There are a lot more to it than that but it is the foundation of why they are useful. The way to think of a templated class is not as a class but as a "Super class". That is, a class that has the ability to take on different representations.
It's not a difficult concept BUT if you don't have a lot of experience with oop you might not really see why they are useful and think they make things more complex. But once you end up having to write very many similar classes that all only differ by the types used then you'll see why they are so useful(they are actually quite powerful because they end up being able to do a lot more).