首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >从长列表中获取引导的快速方法

从长列表中获取引导的快速方法
EN

Stack Overflow用户
提问于 2021-12-08 22:48:09
回答 2查看 242关注 0票数 2

下面的代码工作2-3秒。让x5-10+更快是真的吗?我试着做泊松鞋带,但效果更慢。此外,由于我在更高级别的代码中具有并行化,所以无法使用joblib和多处理特性。

代码语言:javascript
运行
复制
lst = range(1000000)
result = np.random.choice(lst, size=(100, len(lst)), replace=True).mean(axis=1)

我认为主要的问题是np.random.choice的重组,也许它可以用于优化。

EN

回答 2

Stack Overflow用户

发布于 2021-12-09 01:17:26

TL;DR: np.random.choice是经济放缓的主要原因。问题是,在这种情况下,Numpy使用延迟限制的算法,这很难在顺序上做得更好(由于随机访问内存模式)。随机数生成也相当昂贵。

实际上,必须从内存中获取输入列表中的随机索引项。由于输入列表由Numpy转换为连续的4到8 MiB,因此输入数组可能不适合您的CPU缓存。因此,从主RAM中获取值。此外,随机访问模式阻止处理器快速地从RAM加载值。现代主流x86处理器内核可以同时获取大约10个项(这是令人惊讶的,因为代码应该是顺序的)。然而,当前(DDR) RAMs的延迟是about 50-100 ns。因此,获取RAM应该花费大约一秒的1亿个随机项。此外,还必须生成1亿个随机值(相当慢),还必须填充400~800个MiB中间缓冲区。

加快这种延迟限制计算的一个简单方法是使用多线程。您可以使用Numba (或Cython)来实现这一点。此外,可以使用较小的临时数组来减少使用大型Numpy数组的开销。这些方法可以实时计算.

代码语言:javascript
运行
复制
import numba as nb

# Assume the input array is contiguous
@nb.njit('float64[:](int_[::1])', parallel=True)
def parallelShuffle(arr):
    n, m = 100, arr.size
    res = np.empty(n, np.float64)
    for i in nb.prange(n):
        s = 0.0
        tmp = np.random.randint(0, m, m)
        for j in range(m):
            s += lst[tmp[j]]
        res[i] = s / m
    return res

lst = range(1000000)
lst = np.fromiter(lst, dtype=np.int_)  # Fast iterable to Numpy conversion
result = parallelShuffle(lst)

在我的6核计算机上,这个实现比快4.5倍。注意,基于整数的Numba随机数生成器目前比Numpy慢得可怜。

票数 2
EN

Stack Overflow用户

发布于 2021-12-09 04:03:37

如果不将python range对象转换为numpy数组并从中进行选择,则可以获得~3x提升:

代码语言:javascript
运行
复制
result = np.random.choice(1000000, size=(100, 1000000), replace=True).mean(axis=1)

以这种方式选择一组数字与生成相同范围内的数字是完全相同的。不幸的是,这两种方法花费的时间相同:

代码语言:javascript
运行
复制
result = np.random.randint(1000000, size=(100, 1000000)).mean(axis=1)
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70282665

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档