C# 有没有更有效的方法将double转换为float?

C# 有没有更有效的方法将double转换为float?,c#,performance,C#,Performance,我需要将多维双数组转换为锯齿形浮点数组。大小从[2][5]到[6][1024]不等 我很好奇,仅仅循环并将双精度浮点转换到浮点会如何执行,这并不太糟糕,对于[2][5]阵列大约225µs-下面是代码: const int count = 5; const int numCh = 2; double[,] dbl = new double[numCh, count]; float[][] flt = new float[numCh][]; for (int i = 0; i < numCh

我需要将多维双数组转换为锯齿形浮点数组。大小从[2][5]到[6][1024]不等

我很好奇,仅仅循环并将双精度浮点转换到浮点会如何执行,这并不太糟糕,对于[2][5]阵列大约225µs-下面是代码:

const int count = 5;
const int numCh = 2;
double[,] dbl = new double[numCh, count];
float[][] flt = new float[numCh][];

for (int i = 0; i < numCh; i++)
{
    flt[i] = new float[count];
    for (int j = 0; j < count; j++)
    {
        flt[i][j] = (float)dbl[i, j];
    }
}
const int count=5;
常数int numCh=2;
double[,]dbl=新的double[numCh,count];
浮动[][]flt=新浮动[numCh][];
对于(int i=0;i
然而,如果有更有效的技术,我想使用它们。我应该提到,我只对两个嵌套循环进行了计时,而没有对之前的分配进行计时


在做了更多的实验后,我认为99%的时间都花在了循环上,即使没有任务

在您的示例中-我认为您对双/浮点比较的测量程度不如数组访问(具有大量重定向和明显的分隔符检查(用于边界的数组索引异常))那么大(应该是处理器内部指令)


我建议在没有阵列的情况下对测试进行计时。

如果您可以在您的案例中使用列表,您可以使用LINQ方法:

List<List<double>> t = new List<List<double>>();
//adding test data
t.Add(new List<double>() { 12343, 345, 3, 23, 2, 1 });
t.Add(new List<double>() { 43, 123, 3, 54, 233, 1 });
//creating target
List<List<float>> q;
//conversion
q = t.ConvertAll<List<float>>(
        (List<double> inList) => 
        {
            return inList.ConvertAll<float>((double inValue) => { return (float)inValue; });
        }
     );
List t=newlist();
//添加测试数据
t、 添加(新列表(){12343345,3,23,2,1});
t、 添加(新列表(){43,123,3,54,233,1});
//创建目标
清单q;
//转化
q=t.ConvertAll(
(列表中的列表)=>
{
返回inList.ConvertAll((双无效)=>{return(float)inValue;});
}
);
如果速度更快,你必须测量自己。(怀疑)
但是您可以将其并行化,从而加快速度(PLINQ)

我并不认为您可以进一步优化代码,一种选择是使代码并行化,但输入数据大小([2][5]高达[6][1024]左右)我不认为你会有这么多的利润,如果你甚至有任何利润。事实上,我甚至不会麻烦优化这段代码在所有


无论如何,要优化它,我要做的唯一一件事(如果这符合您想要做的),就是只使用固定宽度的数组,而不是锯齿状数组,即使这样会浪费内存。

这将运行得更快,对于小数据来说,并行处理是不值得的。
对于(0,count,(j)=>
对于非常小的数据,它实际上运行得相当慢,这就是我将该部分注释掉的原因

double* dp0;
float* fp0;

fixed (double* dp1 = dbl)
{
    dp0 = dp1;

    float[] newFlt = new float[count];
    fixed (float* fp1 = newFlt)
    {
        fp0 = fp1;
        for (int i = 0; i < numCh; i++)
        {
            //Parallel.For(0, count, (j) =>
            for (int j = 0; j < count; j++)
            {
                fp0[j] = (float)dp0[i * count + j];
            }
            //});
            flt[i] = newFlt.Clone() as float[];
        }
     }
  }
double*dp0;
浮点数*fp0;
固定(双*dp1=dbl)
{
dp0=dp1;
浮动[]新浮动=新浮动[计数];
固定(浮动*fp1=新浮动)
{
fp0=fp1;
对于(int i=0;i
对于(int j=0;j
这运行得更快,因为在.NET中,由于数组边界检查,双重访问双数组确实很费力。
newFlt.Clone()
只是意味着我们没有一直固定和取消固定新指针(因为这样做会有一点开销)

您需要使用
unsafe
code标记运行它,并使用
/unsafe


但实际上,您应该使用接近5000 x 5000(而不是5 x 2)的数据运行,如果某个时间小于1000毫秒,您需要添加更多循环或增加数据,因为在该级别上,cpu活动的微小峰值可能会给您的分析增加大量噪音。

225µs对您来说太慢了?如果您有很多(我是指maany)要转换双倍,请尝试使用.NET 4.0 TPL(任务并行库)在多个CPU上处理。10个元素和5个分配,花费225µs,对我来说听起来很长。请稍作评论,如果您想衡量性能,您应该使用更大的数组大小,当您告诉我您的代码在[2][5]中的性能与225µs一样好时md array我真的不知道它有多好,特别是在不知道您的规格的情况下…@Steve我知道224µs看起来很快,但一切都是相对的,对吧?:)我的数据集不够大,无法保证TPL i在这种情况下,但这是我的建议。没错,这正是我要找的。是我,还是当你有机会在.Net中使用指针时,其他人会得到温暖的模糊感?;)我使用的一个值得注意的技巧是使用局部指针变量,而不是固定指针,我不知道为什么,但这样做实际上会提高性能。与访问固定指针有关,需要进行额外的检查以确保它们仍然有效或可能是其他什么。谢谢,但数据集很小,可以实现性能优势。您的观点很好,而且,对于如此小的数据集,如果不引入人为的延迟和分析开销,就很难知道大部分时间都花在了哪里。