float4 的 NativeArray 如何将其中一个 xyzw 设置为循环中的值?
NativeArray of float4 how to set one of the xyzw to a value in loop?
当循环遍历 float4[]
的 NativeArray 并想要将每个 float4(比方说 y
)的 'fields' 之一设置为一个值时,似乎没有立即可行,因为它是一个临时值。
这个:
NativeArray<float4> naFloat4s ;
void Start ( ) {
naFloat4s = new NativeArray<float4> ( 96000, Allocator.Persistent ) ;
}
void MakeNoise ( ) {
for ( int i = 0 ; i < naFloat4s.Length ; i++ ) {
naFloat4s[i].y = Random.Range ( - 1f, 1f ) ;
}
}
生成关于它是结构的临时值的投诉,无法设置。
如何以最有效的方式克服这个问题,以便不产生垃圾,并且 NativeArray 和 Burst/Jobs 可以尽最大努力尽快完成数万个设置的这个过程?
注意:这里使用的random只是一个例子。假设那里还有其他东西会产生更有趣的东西。
另请注意,执行此操作时,其他值(在本例中为 x、z 和 w)必须保持不变。它们仍然有用,因为它们是。需要的是在整个数组中仅更改 float4 中的一个值。
编辑:根据 Hugo 爵士的评论,固定浮动范围。
回应 Hugo 爵士关于 float4 中的 float 指针的评论:
通过这样做,我得到了指向单个浮动的指针:
void LoopDemoWithPointerToFloatOfFloat4_NativeArray() {
int samples = 2000;
int size_T = UnsafeUtility.SizeOf<float4> ( ) ;
int size_F = UnsafeUtility.SizeOf<float> ( ) ;
int mStepr = size_F * 1 ; // 1 is y's index value in the float4 struct
IntPtr dstPtr = ( IntPtr )NativeArrayUnsafeUtility
.GetUnsafeBufferPointerWithoutChecks ( naFloat4s ) ;
for ( int i = 0 ; i < samples ; i++ ) {
unsafe {
float* yOffset = (float*) (dstPtr + i * size_T + mStepr);
*yOffset = (float)i ;
}
}
}
还没来得及看速度,好像很快。
需要创建一个装备来测试各种秒表....
更新的用法示例:
var p = (float4*)noizADSR.GetUnsafePtr ( );
float stepDekay = 1f / dekayLength ;
ptr = (float*)(p + attakFinish); ptr += nID;
j = overlapping;
for ( int i = attakFinish ; i < noizeLength ; i++, j++, ptr += 4 ) {
*ptr = dekayCrv.Evaluate( j * stepDekay) ;
}
像往常一样,对于任何 struct
(= 值)类型,如果它在数组中,您只能执行
var value = naFloat4s[i];
value.y = Random.Range(-1, 1);
naFloat4s[i] = value;
The indexer ([i]
) 是一个 属性 并且 return 或采用完整的 float4
结构值。
所以如果你会(能够)做到
naFloat4s[i].y = something;
你 会 基本上 return 一个 float4
并改变 returned float4
的 y
零件。但这不会以任何方式改变存储在数组中的值。
更新
指向指针的东西:
我刚做了个小测试,确实如果你真的愿意去unsafe
你可以使用指针。以下测试
private unsafe void Test()
{
var testIndexer = new NativeArray<float4>(amount, Allocator.Persistent);
var testPointer = new NativeArray<float4>(amount, Allocator.Persistent);
Profiler.BeginSample("TEST Indexed");
for (var i = 0; i < testIndexer.Length; i++)
{
var value = testIndexer[i];
value.y = i;
testIndexer[i] = value;
}
Profiler.EndSample();
Profiler.BeginSample("TEST Pointer");
var pointer = (float4*)testPointer.GetUnsafePtr();
for (var i = 0; i < testPointer.Length; i++)
{
(pointer + i)->y = i;
// or also (seems equally fast - 10ms slower on 10.000 elements)
// pointer[i].y = i;
// or also (seems equally fast)
// (*(pointer + i)).y = i;
}
Profiler.EndSample();
for (var i = 0; i < amount; i++)
{
Debug.Log($"indexed: {testIndexer[i].y}, pointer: {testPointer[i].y}");
}
Debug.Assert(testIndexer.ToArray().SequenceEqual(testPointer.ToArray()));
testIndexer.Dispose();
testPointer.Dispose();
}
已经至少快了三倍,这很可能是因为使用索引器您有更多操作(读取值、存储值、写入值)。
一些基准值:
amount = 100
- 索引:0.77 毫秒
- 指针:0.25 毫秒
amount = 1000
- 索引:3.40 毫秒
- 指针:0.67 毫秒
amount = 10000
- 索引:37.39 毫秒
- 指针:7.70 毫秒
我不知道是否有可能直接写入单个浮点指针,但它甚至可能更快。
当循环遍历 float4[]
的 NativeArray 并想要将每个 float4(比方说 y
)的 'fields' 之一设置为一个值时,似乎没有立即可行,因为它是一个临时值。
这个:
NativeArray<float4> naFloat4s ;
void Start ( ) {
naFloat4s = new NativeArray<float4> ( 96000, Allocator.Persistent ) ;
}
void MakeNoise ( ) {
for ( int i = 0 ; i < naFloat4s.Length ; i++ ) {
naFloat4s[i].y = Random.Range ( - 1f, 1f ) ;
}
}
生成关于它是结构的临时值的投诉,无法设置。
如何以最有效的方式克服这个问题,以便不产生垃圾,并且 NativeArray 和 Burst/Jobs 可以尽最大努力尽快完成数万个设置的这个过程?
注意:这里使用的random只是一个例子。假设那里还有其他东西会产生更有趣的东西。
另请注意,执行此操作时,其他值(在本例中为 x、z 和 w)必须保持不变。它们仍然有用,因为它们是。需要的是在整个数组中仅更改 float4 中的一个值。
编辑:根据 Hugo 爵士的评论,固定浮动范围。
回应 Hugo 爵士关于 float4 中的 float 指针的评论:
通过这样做,我得到了指向单个浮动的指针:
void LoopDemoWithPointerToFloatOfFloat4_NativeArray() {
int samples = 2000;
int size_T = UnsafeUtility.SizeOf<float4> ( ) ;
int size_F = UnsafeUtility.SizeOf<float> ( ) ;
int mStepr = size_F * 1 ; // 1 is y's index value in the float4 struct
IntPtr dstPtr = ( IntPtr )NativeArrayUnsafeUtility
.GetUnsafeBufferPointerWithoutChecks ( naFloat4s ) ;
for ( int i = 0 ; i < samples ; i++ ) {
unsafe {
float* yOffset = (float*) (dstPtr + i * size_T + mStepr);
*yOffset = (float)i ;
}
}
}
还没来得及看速度,好像很快。
需要创建一个装备来测试各种秒表....
更新的用法示例:
var p = (float4*)noizADSR.GetUnsafePtr ( );
float stepDekay = 1f / dekayLength ;
ptr = (float*)(p + attakFinish); ptr += nID;
j = overlapping;
for ( int i = attakFinish ; i < noizeLength ; i++, j++, ptr += 4 ) {
*ptr = dekayCrv.Evaluate( j * stepDekay) ;
}
像往常一样,对于任何 struct
(= 值)类型,如果它在数组中,您只能执行
var value = naFloat4s[i];
value.y = Random.Range(-1, 1);
naFloat4s[i] = value;
The indexer ([i]
) 是一个 属性 并且 return 或采用完整的 float4
结构值。
所以如果你会(能够)做到
naFloat4s[i].y = something;
你 会 基本上 return 一个 float4
并改变 returned float4
的 y
零件。但这不会以任何方式改变存储在数组中的值。
更新
指向指针的东西:
我刚做了个小测试,确实如果你真的愿意去unsafe
你可以使用指针。以下测试
private unsafe void Test()
{
var testIndexer = new NativeArray<float4>(amount, Allocator.Persistent);
var testPointer = new NativeArray<float4>(amount, Allocator.Persistent);
Profiler.BeginSample("TEST Indexed");
for (var i = 0; i < testIndexer.Length; i++)
{
var value = testIndexer[i];
value.y = i;
testIndexer[i] = value;
}
Profiler.EndSample();
Profiler.BeginSample("TEST Pointer");
var pointer = (float4*)testPointer.GetUnsafePtr();
for (var i = 0; i < testPointer.Length; i++)
{
(pointer + i)->y = i;
// or also (seems equally fast - 10ms slower on 10.000 elements)
// pointer[i].y = i;
// or also (seems equally fast)
// (*(pointer + i)).y = i;
}
Profiler.EndSample();
for (var i = 0; i < amount; i++)
{
Debug.Log($"indexed: {testIndexer[i].y}, pointer: {testPointer[i].y}");
}
Debug.Assert(testIndexer.ToArray().SequenceEqual(testPointer.ToArray()));
testIndexer.Dispose();
testPointer.Dispose();
}
已经至少快了三倍,这很可能是因为使用索引器您有更多操作(读取值、存储值、写入值)。
一些基准值:
amount = 100
- 索引:0.77 毫秒
- 指针:0.25 毫秒
amount = 1000
- 索引:3.40 毫秒
- 指针:0.67 毫秒
amount = 10000
- 索引:37.39 毫秒
- 指针:7.70 毫秒
我不知道是否有可能直接写入单个浮点指针,但它甚至可能更快。