首页 > 编程语言 >如何在C#中将float[]快速的转换为byte[]

如何在C#中将float[]快速的转换为byte[]

时间:2023-12-21 18:34:50浏览次数:42  
标签:00 C# float 用时 srcArray stopwatch byte 方法 Marshal

昨天喻兄抛出一个问题“如何在C#中将float[]快速的转换为byte[]”。于是开始了尝试。先写了下面的初始化代码

using System.Diagnostics;
using System.Runtime.InteropServices;

Random random = new Random();
//源数组
var srcArray = new float[500 * 1024 * 1024];
//目的数组
var desArraySize = Buffer.ByteLength(srcArray);
byte[] desArray = new byte[desArraySize];
//源数组填充随机数据
for (var i = 0; i < srcArray.Length; i++)
    srcArray[i] = Convert.ToSingle(random.NextDouble());
Stopwatch stopwatch = Stopwatch.StartNew();

最开始想到的肯定是用BitConvert类的GetBytes方法得到一个float的4个byte,然后循环复制。不过这肯定是最慢的方法,因为每次BitConvert.GetBytes方法会创建一个4字节的数组,存在一个内存分配,并且循环一次只能复制4个字节。

//方法1
    {
        Array.Clear(desArray);
        stopwatch.Restart();
        for (var i = 0; i < srcArray.Length; i++)
        {
            var src = srcArray[i];
            var srcBytes = BitConverter.GetBytes(src);
            srcBytes.CopyTo(desArray, i * srcBytes.Length);
        }
        stopwatch.Stop();
        Console.WriteLine("方法1用时:" + stopwatch.Elapsed);
    }

想到C#中的数组在内存上是连续的,直接访问原数组这块内存,然后块复制到目的数据的内存应该是最快的。最开始尝试用的Marshal类,这个类从.NET Framework 2.0开始就存在了,主要就是处理托管和非托管相关的转换。先用Marshal类的UnsafeAddrOfPinnedArrayElement方法得到源数组的托管指针,然后调用Marshal类的Copy方法复制数据。

//方法2
    {
        Array.Clear(desArray);
        stopwatch.Restart();
        IntPtr srcArrayPtr = Marshal.UnsafeAddrOfPinnedArrayElement(srcArray, 0);
        Marshal.Copy(srcArrayPtr, desArray, 0, desArraySize);
        stopwatch.Stop();
        Console.WriteLine("方法2用时:" + stopwatch.Elapsed);
    }

在Windows上测试,上面的Marshal.Copy方法已经比最开始的循环快了一个数量级了。不过Marshal.Copy还是用的托管指针。然后我就在想能不用C语言中的memcpy方法用非托管指针进行复制,会不会更快呢?在C#中使用unsafe代码段可以轻松地得到非托管指针,然后在网上查阅资料后,找到了System.Buffer类中有MemoryCopy方法,应该是对标C语言中的memcpy方法的。

//方法3
    {
        Array.Clear(desArray);
        stopwatch.Restart();
        unsafe
        {
            fixed (void* desArrayPtr = desArray)
            fixed (void* srcArrayPtr = srcArray)
                Buffer.MemoryCopy(srcArrayPtr, desArrayPtr, desArraySize, desArraySize);      
        }
        stopwatch.Stop();
        Console.WriteLine("方法3用时:" + stopwatch.Elapsed);        
    }

使用500MB数据测试5次得到下面结果,经测试方法2和方法3的速度差不多。

------------------
方法1用时:00:00:07.0318303
方法2用时:00:00:00.1493652
方法3用时:00:00:00.1358148
------------------
方法1用时:00:00:06.5965146
方法2用时:00:00:00.1299518
方法3用时:00:00:00.1332787
------------------
方法1用时:00:00:06.4803075
方法2用时:00:00:00.1301812
方法3用时:00:00:00.1294293
------------------
方法1用时:00:00:06.4821344
方法2用时:00:00:00.1294174
方法3用时:00:00:00.1299445
------------------
方法1用时:00:00:06.4693005
方法2用时:00:00:00.1300947
方法3用时:00:00:00.1279827

 

标签:00,C#,float,用时,srcArray,stopwatch,byte,方法,Marshal
From: https://www.cnblogs.com/aaaSoft/p/17919833.html

相关文章

  • 【Docker】关于挂载修改&迁移问题
    如果进行容器挂载迁移,新挂载的目录会导致之前容器内的数据丢失,接下来给大家整理思路之前是没有进行数据挂载的,也就是默认路径#先查看一下默认路径dockerinspect【容器名】#Mounts这里有详细的挂载信息,可以看到最开始的默认路径是home/lib/docker/volumes/b9588a26ea88d44f1......
  • 使用ansible脚本用pt-archiver归档数据
    【背景说明】需要使用ansible来管理删除数据任务,数据量较大,使用pt-archiver工具【环境说明】MySQL主从架构+pt-archiver3.5.5【剧本说明】treeroles/archive_mysql/roles/archive_mysql/├──files│└──percona-toolkit-3.5.5-1.el7.x86_64.rpmpt工具├......
  • 云技术分享 | EC2 之 Windows 忘记密码(二)
    01场景描述紧接上一篇文章《EC2之Windows忘记密码(一)》,本文将介绍解决的第三种方法——磁盘挂载。亚马逊云科技开发者社区为开发者们提供全球的开发技术资源。这里有技术文档、开发案例、技术专栏、培训视频、活动与竞赛等。帮助中国开发者对接世界最前沿技术,观点,和项目,并将......
  • k8s~ingress_service_endpoint_pod四壮士
    在Kubernetes中,Service和Endpoints是两个重要的概念,它们之间存在着密切的关系。Service:Service是Kubernetes中用于定义一组Pod的访问方式的抽象。通过创建Service,可以为一组具有相同标签的Pod提供统一的访问入口,使得客户端可以通过Service来访问这些Pod,而无需了解其具体的IP地......
  • React 之使用 antd 实现全局 loading
    使用antd的Spin实现Loading代码如下:fullLoading.tsximportReactDOMfrom"react-dom/client";import{Spin}from"antd";//全局加载loading//当前请求的个数//当同时有多个请求时,等所有请求完成后再关闭loadingletreqCount=0;//显示loadingfuncti......
  • ThreadLocal的内存泄露?什么原因?如何避免?
    前言在分析ThreadLocal导致的内存泄露前,需要普及了解一下内存泄露、强引用与弱引用以及GC回收机制,这样才能更好的分析为什么ThreadLocal会导致内存泄露呢?更重要的是知道该如何避免这样情况发生,增强系统的健壮性。内存泄露内存泄露为程序在申请内存后,无法释放已申请的内存空间,一......
  • WPF自定义控件之图形解锁控件 ScreenUnLock
    ScreenUnLock与智能手机上的图案解锁功能一样。通过绘制图形达到解锁或记忆图形的目的。本人突发奇想,把手机上的图形解锁功能移植到WPF中。也应用到了公司的项目中。在创建ScreenUnLock之前,先来分析一下图形解锁的实现思路。1.创建九宫格原点(或更多格子),每个点定义一个坐标值......
  • 革命性突破:Great River推出XL高速ARINC 818传感器测试卡
         GreatRiverTechnology荣幸地宣布,与RVS(远程视觉系统)2.0平台合作推出的XL高速ARINC818传感器测试卡正式亮相。这款开创性的测试卡在柯林斯航空电子公司(RTX业务部)和波音公司开发和测试RVS2.0系统中发挥了重要作用。在过去的一年中,GreatRiverTechnology已经成功向柯......
  • opencv图像处理机器学习真实项目教程(python实现)3图像处理基础
    3图像处理基础在本章中,我们将介绍图像处理中的各种操作,首先是基于平移的操作,如旋转和调整大小。读者将学习如何使用OpenCV旋转和调整图像大小,以及如何控制生成图像的大小和方向。本章接着介绍了图像的算术运算,如加法、减法和除法。本章继续以图像运算为主题,介绍图像的位运算,如......
  • Gitlab-CICD
    CICD是什么我们的开发模式经历了如下的转变:瀑布模型->敏捷开发→DevOps(Development、Operations的组合词,是一组过程、方法与系统的统称)后来随着DevOps的兴起,出现了持续集成(ContinuousIntegration)、持续交付(ContinuousDelivery)、持续部署(ContinuousDeployment)的新方法,关于......