Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/asp.net-core/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何有效地计算日志返回_C#_.net_Class_Math_Return - Fatal编程技术网

C# 如何有效地计算日志返回

C# 如何有效地计算日志返回,c#,.net,class,math,return,C#,.net,Class,Math,Return,我有一个多维数组double[,]results,其中每列表示特定项目(如汽车、房屋等)的价格时间序列。我想计算每个时间序列的日志返回,如下所示 日志(价格/价格) 其中t>t1。因此,我将为double[,]结果的每一列生成一个新的日志返回时间序列。 如何在C#中以有效的方式实现这一点?数据量很大,我尝试了以下解决方案: for(int col = 1; col <= C; col++) { for(int row = 1; row <= R; row++) {

我有一个多维数组
double[,]results
,其中每列表示特定项目(如汽车、房屋等)的价格时间序列。我想计算每个时间序列的日志返回,如下所示 日志(价格/价格) 其中t>t1。因此,我将为
double[,]结果的每一列生成一个新的日志返回时间序列。
如何在C#中以有效的方式实现这一点?数据量很大,我尝试了以下解决方案:

for(int col = 1; col <= C; col++)
{
     for(int row = 1; row <= R; row++)
     {
         ret = Math.Log(results[row+1;col]/ results[row;col])
     }
}

for(int col=1;col如果您的计算机有多个内核,您可以轻松提高计算速度。为了亲自尝试,我从创建此函数开始:

Double[,] ComputeLogReturns(Double[,] data) {
  var rows = data.GetLength(0);
  var columns = data.GetLength(1);
  var result = new Double[rows - 1, columns];
  for (var row = 0; row < rows - 1; row += 1)
    for (var column = 0; column < columns; column += 1)
      result[row, column] = Math.Log(data[row + 1, column]/data[row, column]);
  return result;
}
Double[] ComputeLogReturns(Double[] data, Int32 rows, Int32 columns) {
  var result = new Double[(rows - 1)*columns];
  for (var row = 0; row < rows - 1; row += 1)
    for (var column = 0; column < columns; column += 1)
      result[row*columns + column] = Math.Log(data[(row + 1)*columns + column]/data[row*columns + column]);
  return result;
}
在我的4核(8个逻辑核)计算机上,执行100个调用大约需要0.9秒。这比3倍快一点,表明只有物理核而不是逻辑核能够计算对数

现代x86 CPU有一种特殊的指令,称为“矢量化”,允许您对某些计算进行矢量化。我希望MATLAB使用这些指令,这也许可以解释为什么与您自己的C#代码相比,您在MATLAB中的性能要好得多

为了测试SSE,我尝试了绑定到C#的库。该库在NuGet上作为预发行版提供,并具有对数函数。SSE指令仅适用于一维数组,因此我重写了基线函数:

Double[,] ComputeLogReturns(Double[,] data) {
  var rows = data.GetLength(0);
  var columns = data.GetLength(1);
  var result = new Double[rows - 1, columns];
  for (var row = 0; row < rows - 1; row += 1)
    for (var column = 0; column < columns; column += 1)
      result[row, column] = Math.Log(data[row + 1, column]/data[row, column]);
  return result;
}
Double[] ComputeLogReturns(Double[] data, Int32 rows, Int32 columns) {
  var result = new Double[(rows - 1)*columns];
  for (var row = 0; row < rows - 1; row += 1)
    for (var column = 0; column < columns; column += 1)
      result[row*columns + column] = Math.Log(data[(row + 1)*columns + column]/data[row*columns + column]);
  return result;
}
Double[]计算日志返回(Double[]数据,Int32行,Int32列){
var结果=新的双精度[(行-1)*列];
对于(变量行=0;行<行-1;行+=1)
对于(变量列=0;列<列;列+=1)
结果[行*列+列]=Math.Log(数据[(行+1)*列+列]/数据[行*列+列]);
返回结果;
}
在相同的输入和100次迭代的情况下,执行时间现在似乎略少于3秒,这表明一维数组可能会略微提高性能(但从逻辑上讲,不应该这样做,除非是额外的参数检查影响了执行时间)

使用Yeppp!函数变为:

Double[] ComputeLogReturnsSse(Double[] data, Int32 rows, Int32 columns) {
  var quotient = new Double[(rows - 1)*columns];
  for (var row = 0; row < rows - 1; row += 1)
    for (var column = 0; column < columns; column += 1)
      quotient[row*columns + column] = data[(row + 1)*columns + column]/data[row*columns + column];
  var result = new Double[(rows - 1)*columns];
  Yeppp.Math.Log_V64f_V64f(quotient, 0, result, 0, quotient.Length);
  return result;
}
Double[]ComputeLogReturnSSE(Double[]数据,Int32行,Int32列){
var商=新的双精度[(行-1)*列];
对于(变量行=0;行<行-1;行+=1)
对于(变量列=0;列<列;列+=1)
商[行*列+列]=数据[(行+1)*列+列]/数据[行*列+列];
var结果=新的双精度[(行-1)*列];
Yeppp.Math.Log_V64f_V64f(商,0,结果,0,商,长度);
返回结果;
}
我找不到使用Yeppp执行矢量化除法的函数!因此该除法是使用“normal”执行的除法。但是,我仍然认为对数是最昂贵的操作。最初性能很糟糕,100次迭代需要17秒,但后来我注意到Yeppp!中存在一个问题,即作为32位进程运行时性能不佳。切换到64位大大提高了性能,导致大约1.3秒执行时间的onds。去掉函数中的两个数组分配(重复100次)将执行时间降低到大约0.7秒,这比并行实现快。使用
parallel.For
执行乘法将执行时间降低到大约0.4秒。如果是,ppp!有办法执行除法(SSE有)您可能会得到更低的执行时间,这可能会导致速度提高十倍


根据我对SSE的实验,您应该能够实现相当大的性能改进。但是,如果这很重要的话,您可能应该注意精度。SSE日志函数可能会提供与.NET实现稍有不同的结果。

谢谢您的回答。因此,您认为使用Parallel时会有这样的结果吗ld的性能仍然比矢量化计算差?@mickG:我在这里猜测,但我希望SSE会快得多。唯一的问题是,你必须自己使用SSE实现对数,你必须在执行时间和精度之间进行权衡。我相信Intel有一个库你可以使用,但我不知道abo它的可用性和使用C是多么复杂。我知道,所以没有立即的方法来改进计算。我将尝试并行。无论如何,这似乎是一个很好的建议。是并行的。对于任何条件下的矿石,使用最小的计算量,通过开销来补偿开销。ALE?我记得在R中,当并行执行小循环时,与非并行执行相比,TGEER实际上是最差的性能。只有大循环受益于并行执行。C中有类似的事情,或者我总是使用并行吗?对于?@ MICKG:正确的是有并行开销,所以它是并行的。只有当有一个显著的优势时才应该使用,即有1000行可以独立计算,并且每行都需要花费大量的时间来计算。在使用SSE进行了一些测试之后,我也更新了我的答案,结果似乎与我之前关于使用SS的优势的陈述相矛盾E.如果有人对这件事有更多的了解,能为你的问题提供答案,那将是一件很有趣的事情。@mickG:在对SSE有了更多的兴趣之后,我发现它实际上相当快。从托管代码中正确地使用它可能会让你走上一条艰难的道路,但最终结果可能是值得的。