【问题标题】:Numpy faster than pure C? [closed]Numpy 比纯 C 更快? [关闭]
【发布时间】:2019-04-30 00:52:02
【问题描述】:

我有以下 C 代码。在我的机器上,我在 13 秒左右计时。

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main(void) {
    clock_t begin = clock();

    double d = 0;

    for (int i = 0; i < 1e9; i++) {
        d = 1 + rand() * 5 > 10 ? 4 : rand();
    }

    clock_t end = clock();
    double time_spent = (double) (end - begin) / CLOCKS_PER_SEC;

    printf("%f", time_spent);
    return EXIT_SUCCESS;
}

但是这个 numpy 操作,我的时钟只有几分之一秒!

a = np.random.randn(1000, 1000)
b = np.random.randn(1000, 1000)
c = a.dot(b)

考虑到他们正在做相同数量的工作(1e9 次操作),这怎么可能? numpy 是并行化的吗?

【问题讨论】:

  • 你在什么操作系统上运行?如果您使用的是 Linux,请在运行 numpy 操作的同时从命令行运行 top 命令,并直观地检查正在使用的内核数。虽然我怀疑 numpy 在没有你明确告诉它这样做的情况下不会使用并行性。
  • 您的 C 程序实际上在中间有一个 if - 这通常会使 CPU 停顿。
  • 您正在执行非常不同的操作。一方面,您的 Python 正在生成 2e6 伪随机数;您的 C 代码,至少 1e9 除了两个代码都在做的乘法和求和。你宁愿举起一千张纸还是一千颗炮弹?为什么?不一样吗,千千万万?
  • 尝试做 np.random.randn(31623, 31623)
  • 在 c 中,由于循环中的条件,您正在执行超过 10^9 rand() 操作。

标签: python c performance numpy time


【解决方案1】:

你的程序没有做同样的事情。你的C 程序调用rand 至少 10^9 次。另外,您对随机数有条件。

numpy 创建 2 个 1000x1000 数组,它们仅是 2x10^6。对随机值没有条件。点积然后添加了O(n^3) 操作(和一个数组创建),但是非常优化。

因此,您基本上是将C 中的连续rand 调用与python 中更少的randn 调用以及优化操作(dot) 进行比较。

为了获得有效的基准,您应该有 2 个执行完全相同操作的程序。

【讨论】:

  • 矩阵点积取 O(n^3),即 1e9。
  • 但是点沿着共享维度 1000。所以我们在 10^6 处有两个数组,我支持你。但是这个点又增加了 10^3 次操作。回到 10^9
  • 你仍在比较非常不同的操作。 ~10^9 rand() 调用 vs 10^6 nrand() 调用加上乘法/数组创建。对于真正的基准,您应该确保您的程序完全一样。
  • @Arthur-1 random 不是系统调用。
  • 请注意,这两个代码都无条件地进行 1e9 加法和 1e9 乘法。 cca 2e9 rand 调用是最重要的Here 是 glibc 随机数的来源 - 加法、乘法和按位与(对于最简单的 RNG)。
【解决方案2】:

Numpy 拥有多种语言的后端,如 C、C++ 和 Fortran,如 on their docs 所列示的@

随着 Numeric 成熟并发展为 NumPy,人们已经能够 直接在 NumPy 中编写更多代码。通常这段代码足够快 用于生产用途,但有时仍需要 访问编译的代码。要么获得最后一点效率 算法或使其更容易访问广泛可用的代码 用 C/C++ 或 Fortran 编写)

因此,除非您正在编写高度优化的 C 代码,否则它无论如何都会变慢

【讨论】:

    猜你喜欢
    • 2010-10-22
    • 2010-10-11
    • 2014-03-06
    • 2015-06-22
    • 2012-04-28
    • 2021-11-27
    • 2012-11-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多