#Using CommandBufferSystem to update elements of NativeArray which is inside IComponentData

1 messages · Page 1 of 1 (latest)

latent frigate
#

Hello, is the idea even possible? Because afaik using .SetComponent() would result in setting the whole Component, which is not my intention and when I tried it out, I got deallocation Exceptions. I didn't try fixing this approach if there is potentially an easier one

Is there maybe another way to queue some changes for NativeArrays?

My goal:
I want to increment some elements of a NativeArray inside of a IJobEntity.ScheduleParallel(). If I can queue up the incrementation and then do it all at once some time in the future then I could run the Job in parallel, otherwise the Job has to be sequential, since running it in parallel could lead to a race condition.

Potential solution to the problem:
I could think of a way where another NativeArray (arr2) gets used which stores the Indices of the first NativeArray (arr1).
Therefore, after the Job finishes, I could run over arr2 and do arr1[arr2[i]]++.
Since every Entity would have its own Index in arr2, no race condition could happen and writing in parallel would be possible as well (This idea just came up while writing the post)

split plaza
#

don't use native array inside ICD, use DynamicBuffer instead

latent frigate
split plaza
#

is that singleton?

latent frigate
#

yes

#

it takes a long time for the array size to change

#

so i wouldnt see it as dynamic tbh

split plaza
#

schedule simple parallel job

#

and use this array as a field

latent frigate
#

that's what I am currently doing with .Schedule() works like a charm, using .ScheduleParallel() will lead to race condition since multiple entities "Unit" could write to the same Index in the array

split plaza
#

use IJobParallel

#

not IJE

#

oh wait

#

I see what you mean now

#

well yeah, that's unsafe

#

so just schedule normally

#

or rework the way you use that data

latent frigate
#

Yeah schedule or reworking the data are the only things I can do
but I still hoped for an "easy way" which just lets me queue some operations

split plaza
#

queing operations is even more expensive than locking

#

(unless it's batched call with no memory passed around)

latent frigate
#

I see, that's interesting
Well, thanks for clearing things up!

glass rapids
#

you could also use atomic counters if that's the only race condition https://docs.unity3d.com/Packages/com.unity.collections@2.1/api/Unity.Collections.LowLevel.Unsafe.UnsafeAtomicCounter32.html

hallow bobcat
#

just remember, you can't bake native containers

#

even if it works in editor, it won't work in a build

latent frigate
latent frigate
hallow bobcat
#

yeah thats fine

#

just very common for people to try bake containers, think it's working and only find out later so i just like to check

latent frigate
hallow bobcat
#

when reading dynamic buffers you should use AsArray to reinterpret it into a nativearray

#

and if your buffer is small enough to fit in the chunk the buffer will be faster

latent frigate
#

Really? I could swear I read a post from the former CTO in the forum about that (as a comment)

hallow bobcat
#

if you just use it as a dynamic buffer it's not great because
return UnsafeUtility.ReadArrayElement<T>(BufferHeader.GetElementPointer(m_Buffer), index);

#

it has to dot he getelementpointer every acces

#

but if you AsArray it first, it only has the overhead of doing it once

latent frigate
hallow bobcat
#

General rule for C#

#

To is a copy
As is a reinterpret

#

so ToArray would make a new array and copy the data to it

#

AsArray simply points to the same memory

#

but yeah outside of a chunk, dynamic buffer just uses the same persistent allocator you're using for your native array
byte* newData = (newCapacity <= internalCapacity) ? (byte*)(header + 1) : (byte*)Memory.Unmanaged.Allocate(newSizeInBytes, alignment, Allocator.Persistent);

latent frigate
#

I see thanks for the info, i will look at everything thoroughly when I am on the PC