我需要将多维双数组转换为锯齿状浮点数组。大小将从[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];
}
}
但是,如果有更有效的技术,我想使用它们。我应该提一下,我只计时两个嵌套循环,而不是之前的分配。
经过多一点实验后,我认为即使没有作业,99%的时间也会在循环中燃烧!
答案 0 :(得分:6)
这样运行得更快,对于小数据而言,它不值得做Parallel.For(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[];
}
}
}
这样运行得更快,因为双重访问双数组[,]
由于数组边界检查而在.NET中真的很费力。 newFlt.Clone()
只是意味着我们不是一直在修复和取消固定新指针(因为这样做会有轻微的开销)
您需要使用unsafe
代码标记运行它并使用/UNSAFE
但实际上你应该运行的数据接近5000 x 5000而不是5 x 2,如果需要的时间少于1000毫秒,你需要添加更多的循环或增加数据,因为在那个级别cpu活动的次要峰值可以为你的分析添加很多噪音。
答案 1 :(得分:0)
在你的例子中 - 我认为你不会像数组访问那样(这应该是处理器内部指令)测量双/浮点数比较(它有很多重定向加上明显的.... aray定界符检查(对于数组索引的范围异常)。
我建议在没有阵列的情况下进行测试。
答案 2 :(得分:0)
如果您在案例中也可以使用列表,则可以使用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; });
}
);
如果它更快,你必须衡量自己。 (疑) 但是你可以将它并行化,这可以把它搞定(PLINQ)
答案 3 :(得分:0)
我真的不认为你可以更多地优化你的代码,一种选择是使你的代码并行但是你的输入数据大小([2] [5]到[6] [1024]左右)如果你有任何利润,我不会为你赢利。事实上,我根本不打算优化那段代码......
无论如何,为了优化它,我唯一要做的事情(如果它适合你想做的事情)就是使用固定宽度的数组而不是锯齿状的数组,即使你会浪费内存