THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 07/05/2006 at 15:17, xxxxxxxx wrote:
Cinema 4D Version: 9.5
Platform: Windows ; Mac ;
Language(s) : C++ ;
I have a channel shader and am allocating a vector container in InitRender and free it in FreeRender().
I am then filling the container in my Output function only at the first call (the next Output calls don´t get into the filling function).
This works fine for a single CPU but it crashes everytime in a multiple CPU context.
How can I overcome this problem without allocating the container in the Output function (as I am not sure if this is a safe operation due to freeing the container again. Yes, I can free it in FreeRender but is this safe for multiple CPUs???)
On 08/05/2006 at 06:13, xxxxxxxx wrote:
You don't want to allocate anything in the Output function
If the content of the container changes during calls to Output, you must allocate one container for each CPU.
You will have to do something like this in InitRender.
p_data = bNew std::vector<Data>[ irs->vd->GetCPUCount() ]
In Output you can access it by
std::vector<Data> &data; = p_data[ vd->GetCurrentCPU() ];
Then free it in FreeRender
bDelete( p_data );
If you fill the array only at the first call, you should think about whether it's possible to fill it in InitRender, and leave the data unchanged during rendering. That way, you would avoid a lot of overhead.
Btw. InitRender and FreeRender are called only once per shader within the main rendering thread. So you can safely allocate and free anything you want to.
On 08/05/2006 at 06:20, xxxxxxxx wrote:
first of all thanks for your reply but I tried this already and this crashes too. Another problem is that I cannot fill the data in InitRender as I explicitely need vd->op. Or is there a way that I can get vd->op (so the RayObject my shader is attached to) in InitRender as I am already allocating my vector in InitRender, free it in FreeRender respectively, but am forced to fill it in my first Output call (due to my limited knowledge how to retrieve my RayObject).
On 10/05/2006 at 07:34, xxxxxxxx wrote:
Hmm, nobody knows how to retrieve vd->op from within InitRender()? Or is it not possible?
On 10/05/2006 at 15:53, xxxxxxxx wrote:
Hmm.. i've reconsidered.. i think it would not make much sense to have vd->op it in InitRender. A Material can be attached to many objects. So it's only avaiable when a shader is evaluated for a specific object.
Unfortunately i have no idea how to find out what objects a material with your shader is attached to.. if possible at all. Perhaps David can help here. He must have some experience with this from S&T;.
On 11/05/2006 at 02:00, xxxxxxxx wrote:
Hmm, thanks Michael for your help. I hope Dave or Mikael can help me (at least giving the information if it´s possible or not!) on this. But I think it should be possible to retrieve the object...somehow.
On 11/05/2006 at 04:31, xxxxxxxx wrote:
A shader isn't attached to any objects so in initrender it would be fairly tricky, I guess you'd have to search through all objects, materials and shaders for a link to your own.
So Output looks like the way to go. InitRender will only be called per each used link to your shader, same with FreeRender. Not the number of render threads. If you have data you are going to change per thread you need the memory allocated per thread (cpu number).
Why is it crashing? are you changing data that is used by multiple threads? One shader could be on many objects, so your shader must handle the case of output getting called for different objects.
Its not a good idea to do much in output, but if you need to and its only on the first case of a new object then its probably ok (just need to watch the usual thread issues).
If you are going to access any data from multiple threads you must use some form of lock (spinlock or semaphore), this will slow it down. You will have to balance memory v speed v cpus, if you need to init some data per each object then with multiple cpus you can do this per cpu so they never change any of the same variables/data, but then this is double the memory and double the init calls, or, you block access during read/write (spinlock probably) but then slow the whole thing down with the spinlocks. First I'd find out why its crashing, what illegal thing does it do? then test the speed v memory v cpu combination for one you are happy with.
On 11/05/2006 at 04:43, xxxxxxxx wrote:
Thank you Dave for these information! I actually am not doing anything illegal.
Am allocating a vector instance in InitRender:
arr = gNew std::vector<float>;
and am filling it in the output function by attaching them with arr->push_back(x);
I do this for one object only, with a single instance of my shader.
I also tried checking for which CPU is currently processed with vd->GetCurrentCPU() and then fill the according vector, but that also crashes. (it must be this cause when I remove the push_back call, it doesn´t crash).
I have another look at my function, maybe I missed something (will also check semaphores, but speed is an issue as the shader is already very heavy on calculations).
Will get back to report.
Thanks so far!
On 13/05/2006 at 06:58, xxxxxxxx wrote:
Hmm... perhaps it is a problem with std::vector.. it could be that the dynamically resizing memory routines screw up in a multithreaded context for some reason. Though i'm sure they should not
First you could try to preallocate enougth mem in InitRender. Just for testing, so you know how to alloc enougth for the objects.
In InitRender this should handle the allocation...
arr->reserve( cnt );
And in Output...
arr->push_back( x );
... will basically just do arr[size++]=x
If that works you could try not using the vector class. I would try now to replace it by a simple array allocated with bNew or GeAlloc. ( Actually one array per thread, to be sure the threads don't interfere )
On 16/05/2006 at 13:19, xxxxxxxx wrote:
You could also see if the std::vector problems can be avoided by having your own allocator. I'm afraid I can't help you more than that, since I've only used STL within single threaded context in C4D.
On 24/05/2006 at 11:49, xxxxxxxx wrote:
Thx Michael and Mikael. Reserving memory didn´t help though, and not using vector class doesn´t work either (tried usual array and also GeDynamicArray).
I´ll keep digging.