当前位置: 首页 > 知识库问答 >
问题:

使用泰勒级数加速计算

章威
2023-03-14

在数学中,泰勒级数对于用低次多项式逼近函数是很重要的。

我想看看这样的近似如何有帮助,例如为了加快计算速度。让我们使用著名的泰勒级数:

log(1+x) = x + 0.5 * x^2 + (error term)

从道德上讲,计算2次多项式的值应该比计算log快得多。

因此,一个测试代码:

import numpy, time

def f(t):
    return t + 0.5 * t ** 2
f = numpy.vectorize(f)  

s = time.time()
for i in range(100):
    x = numpy.random.rand(100000) 
    numpy.log(1 + x)
print time.time() - s          # 0.556999921799 seconds

s = time.time()
for i in range(100):
    x = numpy.random.rand(100000)
    f(x)
print time.time() - s          # arghh! 4.81500005722 seconds

为什么多项式法比实际测井慢10倍?我期待的正好相反。

PS:这个问题可能在SO和math.SE.

共有2个答案

向子安
2023-03-14

使用Python Numpy,它可能在这里和那里进行了优化,因此不可能真正对log(1x)vsx 0.5*x^2进行基准测试。所以我搬到了C。

对数的每次操作时间:19.57 ns
对数的2阶泰勒展开的每次操作的时间:3.73 ns

所以大约是x5因素!

#include <iostream>
#include <math.h>
#include <time.h>
#define N (1000*1000*100)
#define NANO (1000*1000*1000)

int main()
{
  float *x = (float*) malloc(N * sizeof(float));
  float y;
  float elapsed1, elapsed2;
  clock_t begin, end;
  int i;

  for (i = 0; i < N; i++) 
    x[i] = (float) (rand() + 1) / (float)(RAND_MAX);

  begin = clock();
  for (i = 0; i < N; i++) 
    y = logf(x[i]);
  end = clock();
  elapsed1 = float(end - begin) / CLOCKS_PER_SEC / N * NANO;

  begin = clock();
  for (i = 0; i < N; i++) 
    y = x[i] + 0.5 * x[i] * x[i];  
  end = clock();
  elapsed2 = float(end - begin) / CLOCKS_PER_SEC / N * NANO;

  std::cout << "Time per operation with log: " << elapsed1 << " ns\n";  
  std::cout << "Time per operation with order-2 Taylor epansion: " << elapsed2 << " ns";

  free(x);

}
江迪
2023-03-14

使用 numpy 的矢量化操作几乎总是比您自己的代码中的任何尝试优化都快。正如@Divakar提到的,矢量化实际上只是编写 for 循环的一种便捷方法,因此您的代码将比 numpy 的本机代码慢。

将 numpy 的优化例程替换为标准 python 代码表明您的方法速度大致相同。

import math, numpy, time


def f(t):
    return t + 0.5 * t ** 2

x = numpy.random.rand(1000000)

s = time.time()
for num in x:
    math.log(1 + num)
print (time.time() - s  )  

s = time.time()
for num in x:
    f(num)
print (time.time() - s)      

结果:

1.1951053142547607
1.3485901355743408

近似速度稍慢,但求幂非常昂贵。将t**2替换为t*t可以得到很好的改进,并允许近似略优于python的

1.1818947792053223
0.8402454853057861

编辑:或者,由于这里的重要教训是优化的科学库几乎可以在一周的任何一天都优于手工编码的解决方案,这是迄今为止最快的泰勒级数近似值与Numpy的矢量化操作。请注意,唯一的大变化是矢量化在近似值函数上没有调用,因此默认使用Numpy的矢量化操作。

import numpy, time

def f(t):
    return t + 0.5 * t ** 2

x = numpy.random.rand(1000000)
s = time.time()
numpy.log(1 + x)
print (time.time() - s)

s = time.time()
x = numpy.random.rand(100000)
f(x)
print (time.time() - s  )

结果:

0.07202601432800293
0.0019881725311279297

在这里,矢量化近似比Numpy的矢量化log快一个数量级。

 类似资料:
  • 我需要对我的递归方法的一些洞察力来计算辛泰勒级数,它不能正常工作。该方法调用了另外两个递归方法,即递归pow方法和递归阶乘方法。我将我的发现与迭代罪方法进行了比较,给了我正确的解决方案。我的递归罪方法中缺少什么? sin(x)= x - x^3/3的近似值!x^5/5!-x^7/7!...

  • 这是我的代码: 但它不起作用并显示此错误:

  • 我有一个作业,教授要我们用泰勒级数计算sin(x)。他希望我们在两个连续分数之间的差小于10^-6时停止迭代。 最后,我说,例如x^5/5!与(x^3/3!)*相同(x^2/4*5),所有分数都是如此。所以我可以保留之前计算的分数,并在下一次迭代中使用。问题是,我最终得到的数字与它的实际罪过有点偏差,我不知道为什么。提前谢谢。这是我的代码:

  • 我使用泰勒级数来计算< code>sin()。对原罪的泰勒级数是: 我使用的实现如下所示: 据我所知,该代码是多项式的项的近似(换句话说,该近似是从零到 系列编写相同类型的实现。 你能帮我理解一下吗?

  • 我试着做x正弦的泰勒展开,但是如果x大于150度,函数就会发散。 这是我的代码: 在这里,我将自治领绑定为[0,2pi]。 这里,我定义了一个阶乘函数 这是sin(x)的Taylor(Maclaurin)级数展开式 } 问题是它必须在[0,2pi]中为x定义,所以我不知道该怎么做。 谢谢

  • 加速计 jd.startAccelerometer(Object object) 开始监听加速度数据。 参数 Object object 属性 类型 默认值 必填 说明 interval string normal 否 监听加速度数据回调函数的执行频率 success function 否 接口调用成功的回调函数 fail function 否 接口调用失败的回调函数 complete funct