memcpy NativeArray Index to NativeArray Index, Length,怎么办?

Posted

技术标签:

【中文标题】memcpy NativeArray Index to NativeArray Index, Length,怎么办?【英文标题】:memcpy NativeArray Index to NativeArray Index, of Length, how to do? 【发布时间】:2021-11-01 03:47:20 【问题描述】:

Unity 中的 NativeArrays 没有从一个到另一个的部分复制功能。

有多种解决方法(NativeSlices 和 GetSubArray),但理想的方法是零检查、全信任、memcpy。

然而,我能想到的最接近的是这个,它什么也没做;

using Unity.Collections ;
using Unity.Collections.LowLevel.Unsafe ;

namespace Unity.Collections 
  public static class NativeArrayExtensions 
    public static unsafe void CopySuperFast <T> (
      this NativeArray<T> src, int srcIndex,
      NativeArray<T> dst, int dstIndex,
      int length ) where T : struct 
      
      GCHandle dstHandle = GCHandle.Alloc ( dst, GCHandleType.Pinned ) ;
      GCHandle srcHandle = GCHandle.Alloc ( src, GCHandleType.Pinned ) ;
      UnsafeUtility.MemCpy ( 
                            ( void* ) ( dstHandle.AddrOfPinnedObject (  )
                                      + dstIndex * UnsafeUtility.SizeOf<T> ( ) ), 
                             ( void* ) (  srcHandle.AddrOfPinnedObject ( ) 
                                       + srcIndex * UnsafeUtility.SizeOf<T> ( ) ), 
                            length ) ;
      dstHandle.Free (  );
      srcHandle.Free (  ) ;
    
  

【问题讨论】:

是什么让你觉得NativeSlice是个问题?为什么要零检查? @Charlieface 这是一个合成器。我正在对信号缓冲区需求进行所有监控,因此在确定缓冲区所需的块部分的过程中完成了所有检查。不再需要检查。至于 Slice 的问题,它比直接的 memcpy 慢很多,因为它使用检查和跨步。没有检查和大步就没有办法使用它。 SubArray 是当前最快的选项,但也有很多冗余,并且比没有检查的理想化 memcpy 慢。 越快、越精简、越高效,就可以添加越多的声音、声音处理和效果,从而带来更多的声音动态、更好的声音和更多的乐趣。因此,渴望找到最好和最快的方法来做到这一点。 我认为我最大的问题是将索引位置指示器(dstIndexsrcIndex)及其伴随的每个类型存储要求的大小转换为void* 指针。我不确定如何将 int 转换为与指针相关的递增类型,更不用说类型的长度了。 【参考方案1】:

我认为这不能回答您的问题,但我无法将其正确格式化为评论。

namespace Unity.Collections

    public static class NativeArrayExtensions
    
        public static unsafe void CopySuperFast<T>(
          this NativeArray<T> src, int srcIndex,
               NativeArray<T> dst, int dstIndex,
          int length
          ) where T : unmanaged
        
            T* srcPtr = (T*)NativeArrayUnsafeUtility.GetUnsafeBufferPointerWithoutChecks(src);
            
                var d = dst.GetUnsafePtr();
                UnsafeUtility.MemCpy(d, srcPtr + dstIndex, sizeof(T) * length);
            
        
    

上面的 sn-p 未经测试,我不确定它是否会起作用。更多将其留在这里作为您可能弄清楚的起点。

【讨论】:

你在我对事物的理解之前已经跳跃了几十年。为什么使用非托管?这与使用 Struct 相比是什么?对不起,无知是我的好朋友。 GetUnsafeBufferPointerWithoutChecks 你是怎么找到这颗宝石的? 我无法改变这个不受管理的想法来做任何事情。它可能正在改变西方(或东方)的记忆方式,但它似乎没有做任何事情,因为目的地位于。 这个例子是来自我链接的帖子和我在文档中遇到的各种功能的科学怪人。关于我为什么使用任何东西的具体细节,请参见文档页面。会链接它们,但在移动设备上,所以有点痛苦。 有点小丑。想看的可以链接maindoc【参考方案2】:

已编辑:根据@TEEBQNE 的建议和想法添加了第二种方式

我已经完成了以下工作,但它在将 void* 传输到 IntPtrs 以进行数学运算方面可能根本不是最优的,然后必须在最后返回到 (void*) 指针:

    using Unity.Collections ;
using Unity.Collections.LowLevel.Unsafe ;

namespace Unity.Collections 
  public static class NativeArrayExtensions 
    public static unsafe void CopySuperFast <T> (
      this NativeArray<T> src, int srcIndex,
           NativeArray<T> dst, int dstIndex,
      int length 
      ) where T : struct 
      UnsafeUtility.MemCpy ( 
                            destination : ( void* ) ( ( IntPtr ) dst.GetUnsafePtr ( ) 
                                       + dstIndex * UnsafeUtility.SizeOf<T> ( ) ), 
                             source :     ( void* ) ( ( IntPtr ) src.GetUnsafePtr ( ) 
                                       + srcIndex * UnsafeUtility.SizeOf<T> ( ) ),
                             size :       length * UnsafeUtility.SizeOf<T> ( ) 
                                          ) ;
    
    // a second idea, based on TEEBQNE's suggestions
    public static unsafe void CopySuperFastWithoutChecks <T> (
      this NativeArray<T> src, int srcIndex,
           NativeArray<T> dst, int dstIndex,
      int length 
      ) 
      where T : unmanaged 
     
      var size_T = UnsafeUtility.SizeOf<T> ( ) ; 
      var srcPtr = (IntPtr)NativeArrayUnsafeUtility.GetUnsafeBufferPointerWithoutChecks ( src ) ; 
      var dstPtr = (IntPtr)NativeArrayUnsafeUtility.GetUnsafeBufferPointerWithoutChecks ( dst ) ;
      
      UnsafeUtility.MemCpy ( 
                            destination :( void* ) ( dstPtr + dstIndex * size_T), 
                            source :     ( void* ) ( srcPtr + srcIndex * size_T ), 
                            size :       length * size_T 
                                         ) ; 
   
  

【讨论】:

你可能已经偶然发现了这个Unity post,但为了以防万一,决定把它放在这里。最后一篇文章与您尝试实现的相似,但采用了托管数组的范围并将MemCpy 用于 NativeArray。 我几乎不明白我做了什么,并从 *** 的一篇关于 C 指针和 long 的文章以及另一篇关于 GCHandle 是如何浪费时间的文章中收集到。这个论坛帖子......我真的不明白他最后在做什么。它似乎比我正在做的更有效。会阅读,凝视深渊一段时间。 不,不明白。他似乎凭空得到了一个 srcPtr。除非这是与生俱来的……不……我无法真正理解最后一篇文章中发生的事情。它的工作原理对您有意义吗? 据我了解,这是因为输入的数组是托管数组。归根结底,数组只是指针,所以我相信这就是在fixed (T * srcPtr = array) 线上进行转换的方式。特别是在使用 fixed 关键字时。据我了解,该帖子似乎对您没有太大帮助,因为NativeArray 不能与fixed 一起使用。

以上是关于memcpy NativeArray Index to NativeArray Index, Length,怎么办?的主要内容,如果未能解决你的问题,请参考以下文章

float4 的 NativeArray 如何将其中一个 xyzw 设置为循环中的值?

java调用javascript时,如何将NativeArray或NativeObject转换成java实体或者HashMap,List对象

WebAssembly Heapf64.set 的文档在哪里

关于c语言数组的memcpy的一个问题

STM32对memcpy的调用导致hardfault(对memcpy本身的调用,而不是memcpy的执行)

memcpy和strcpy的区别