当前位置: 首页 > 面试题库 >

Numpy Pure Function用于性能,缓存

扶珂
2023-03-14
问题内容

我正在用numpy编写一些中等性能的代码。该代码将位于计算的最内层循环中,其运行时间以小时为单位。快速计算表明,在计算的某些变化中,此代码将被执行大约10
^ 12次。

因此,函数是计算sigmoid(X),另一个函数是计算其导数(梯度)。Sigmoid具有以下特性:对于
y = sigmoid(x),dy / dx = y(1-y)
在numpy的python中,它看起来像:

sigmoid = vectorize(lambda(x): 1.0/(1.0+exp(-x)))
grad_sigmoid = vectorize(lambda (x): sigmoid(x)*(1-sigmoid(x)))

可以看出,这两个函数都是纯函数(没有副作用),因此它们是理想的记忆选择,至少就短期而言,我担心缓存每次对S型信号的调用:存储10 ^
12个浮点数将占用数TB的RAM。

是否有优化此方法的好方法?
python是否会发现它们是纯函数,并在适当时为我缓存它们?
我有什么担心的吗?


问题答案:

这些功能已经存在于scipy中。乙状结肠功能可用scipy.special.expit

In [36]: from scipy.special import expit

expit向量化S型函数比较:

In [38]: x = np.linspace(-6, 6, 1001)

In [39]: %timeit y = sigmoid(x)
100 loops, best of 3: 2.4 ms per loop

In [40]: %timeit y = expit(x)
10000 loops, best of 3: 20.6 µs per loop

expit 比自己实现公式还快:

In [41]: %timeit y = 1.0 / (1.0 + np.exp(-x))
10000 loops, best of 3: 27 µs per loop

逻辑分布的CDF是S形函数。它可以作为的cdf方法使用scipy.stats.logistic,但cdf最终会调用expit,因此使用该方法毫无意义。您可以使用该pdf方法来计算Sigmoid函数的导数,也可以使用_pdf开销较小的方法,但是“自己滚动”的方法更快:

In [44]: def sigmoid_grad(x):
   ....:     ex = np.exp(-x)
   ....:     y = ex / (1 + ex)**2
   ....:     return y

时序(x的长度为1001):

In [45]: from scipy.stats import logistic

In [46]: %timeit y = logistic._pdf(x)
10000 loops, best of 3: 73.8 µs per loop

In [47]: %timeit y = sigmoid_grad(x)
10000 loops, best of 3: 29.7 µs per loop

如果要使用的值太短了,请谨慎执行。指数函数很容易溢出。 logistic._cdf比我快速实现的功能更强大sigmoid_grad

In [60]: sigmoid_grad(-500)
/home/warren/anaconda/bin/ipython:3: RuntimeWarning: overflow encountered in double_scalars
  import sys
Out[60]: 0.0

In [61]: logistic._pdf(-500)
Out[61]: 7.1245764067412855e-218

使用sech**21/cosh**2)的实现比上面的要慢一些sigmoid_grad

In [101]: def sigmoid_grad_sech2(x):
   .....:     y = (0.5 / np.cosh(0.5*x))**2
   .....:     return y
   .....:

In [102]: %timeit y = sigmoid_grad_sech2(x)
10000 loops, best of 3: 34 µs per loop

但是它可以更好地处理尾巴:

In [103]: sigmoid_grad_sech2(-500)
Out[103]: 7.1245764067412855e-218

In [104]: sigmoid_grad_sech2(500)
Out[104]: 7.1245764067412855e-218


 类似资料:
  • 我已经在solrcloud 4.3.0中为我的索引配置了solr缓存。我还将自动提交策略配置为1h hard commit和opensearcher false。虽然我没有重新打开searcher,但似乎每1小时我的缓存就会被刷新并重置。据我所知,只有关闭和打开新的搜索程序才能导致缓存被刷新。但我不明白为什么会这样?

  • 我必须使用StackExhange.redis C#在redis缓存中频繁添加N个(独立的)项,每个项都有不同的过期时间,以便在客户端有最小的时间,在服务器端有最小的阻塞和成本。Redis服务器每秒将收到数百个get请求,所以我不想打乱get时间。 我已经阅读了这里的文档并在这里回答。我找不到一个执行此操作的方法。考虑到不同的选择: null

  • ES 内针对不同阶段,设计有不同的缓存。以此提升数据检索时的响应性能。主要包括节点层面的 filter cache 和分片层面的 request cache。下面分别讲述。 filter cache ES 的 query DSL 在 2.0 版本之前分为 query 和 filter 两种,很多检索语法,是同时存在 query 和 filter 里的。比如最常用的 term、prefix、rang

  • 我有一个相当大的java ee应用程序,它有一个巨大的类路径来执行大量的xml处理。目前,我正试图通过取样探查器来加速我的一些功能和定位缓慢的代码路径。 我注意到的一件事是,特别是我们的代码中有等调用的部分非常慢。我一直跟踪到方法,总是创建一个新的实例。在javadoc中,我找到了关于缓存的以下说明: 提供程序是懒惰地定位和实例化的,即按需提供。服务加载器维护到目前为止已加载的提供程序的缓存。迭代

  • 如果我试图缓存一个巨大的(例如:100GB表),当我对缓存的执行查询时,它会执行全表扫描吗?火花将如何索引数据。火花留档说: Spark SQL可以通过调用Spark,使用内存中的列格式缓存表。目录cacheTable(“tableName”)或dataFrame。缓存()。然后Spark SQL将只扫描所需的列,并将自动调整压缩以最小化内存使用和GC压力。你可以打电话给spark。目录uncac

  • 在本章中,我们将了解Grav中的性能和缓存概念。 表现(Performance) 术语“性能”指的是系统性能,使其能够处理更高的系统负载并修改系统以处理更高的负载。 考虑以下与Grav表现有关的要点 - 要获得更好的opcache性能,可以使用PHP opcache和usercache 。 opcache适用于PHP 5.4,使用PHP 5.5,PHP 5.6和Zend opcache可以更快地运