python vs C++ 谁更快

背景

  1. 我非常喜欢编程语言,之前写过rust、R、python、C++等。
  2. 我的第一门语言就是R语言,然后在比较掌握R语言之后,又花了很长一段时间学习RCPP。
  3. 我觉得不管是会R还是说会python,都应该会C\C++。
  4. C\C++运行效率太顶了。牛!

主要内容

最近也刚好C之类的内容,这里就简单分享一个我遇到的非常有意思的内容:使用C和python两种编程语言、通过蒙特卡洛方法计算圆周率PI。

蒙特卡洛计算圆周率PI

蒙特卡洛计算圆周率PI其实是一个非常经典的案例,在R仿真里面,也都有。


基本上案例如下:

  1. 在一个边长为1的正方形里面,有一个半径为1/2的圆。
  2. 正方形和圆共一个中心点。圆内切正方形。
  3. 向这个正方形里面投点,计算点落在圆内的数量。落在圆内点的数量比上总点数就是等于 π / 4 \pi/4 π/4

那么按照这个思想,只要是不断的生成若干个点,计算占比即可。

C代码

这里先分享一个C语言的代码:

#include <stdlib.h>
#include <stdio.h>
#include <chrono>
#include <array>

#define N_POINTS 10000000
#define N_REPEATS 5

float estimate_pi(int n_points) {
   double x, y, radius_squared, pi;
   int within_circle=0;

   for (int i=0; i < n_points; i++) {
      x = (double)rand() / RAND_MAX;
      y = (double)rand() / RAND_MAX;

      radius_squared = x*x + y*y;
      if (radius_squared <= 1) within_circle++;
   }

   pi=(double)within_circle/N_POINTS * 4;
   return pi;
}

int main() {
    double avg_time = 0;

    srand(42);

    for (int i=0; i < N_REPEATS; i++) {
        auto begin = std::chrono::high_resolution_clock::now();
        double pi = estimate_pi(N_POINTS);
        auto end = std::chrono::high_resolution_clock::now();
        auto elapsed = std::chrono::duration_cast<std::chrono::nanoseconds>(end - begin);
        avg_time += elapsed.count() * 1e-9;
        printf("Pi is approximately %g and took %.5f seconds to calculate.\n", pi, elapsed.count() * 1e-9);
    }

    printf("\nEach loop took on average %.5f seconds to calculate.\n", avg_time / N_REPEATS);
}


这里在clion里面运行一下,可以看到非常的快,基本上都是在0.19秒左右。

python代码

既然c语言这么快,那python是什么情况,运行效率如何,这里给到python代码:

import random
import time
import argparse


def estimate_pi(
    n_points: int,
    show_estimate: bool,
) -> None:
    """
    Simple Monte Carlo Pi estimation calculation.

    Parameters
    ----------
    n_points
        number of random numbers used to for estimation.
    show_estimate
        if True, will show the estimation of Pi, otherwise
        will not output anything.
    """
    within_circle = 0

    for _ in range(n_points):
        x, y = (random.uniform(-1, 1) for v in range(2))
        radius_squared = x**2 + y**2

        if radius_squared <= 1:
            within_circle += 1

    pi_estimate = 4 * within_circle / n_points

    if not show_estimate:
        print("Final Estimation of Pi=", pi_estimate)


def run_test(
    n_points: int,
    n_repeats: int,
    only_time: bool,
) -> None:
    """
    Perform the tests and measure required time.

    Parameters
    ----------
    n_points
        number of random numbers used to for estimation.
    n_repeats
        number of times the test is repeated.
    only_time
        if True will only print the time, otherwise
        will also show the Pi estimate and a neat formatted
        time.
    """
    start_time = time.time()

    for _ in range(n_repeats):
        estimate_pi(n_points, only_time)

    if only_time:
        print(f"{(time.time() - start_time)/n_repeats:.4f}")
    else:
        print(
            f"Estimating pi took {(time.time() - start_time)/n_repeats:.4f} seconds per run."
        )


def positive_integer(value: str) -> int:
    """Check for positive integer in arg_parse."""
    int_value = int(value)

    if int_value <= 0:
        raise argparse.ArgumentTypeError(f"{value} is an invalid positive int value")

    return int_value


def main(arguments=None):
    """Main loop in arg parser."""
    parser = argparse.ArgumentParser()
    parser.add_argument(
        "-p",
        "--n_points",
        help="Number of random points to use for estimating Pi.",
        type=positive_integer,
        default=1_000_000,
    )
    parser.add_argument(
        "-r",
        "--n_repeats",
        help="Number of times to repeat the calculation.",
        type=positive_integer,
        default=5,
    )
    parser.add_argument(
            "--only-time",
            action='store_true',
            default=False,
    )
    args = parser.parse_args()

    run_test(
        args.n_points,
        args.n_repeats,
        args.only_time,
    )


if __name__ == "__main__":
    main()


这里是python的运行结果,基本上在1.5秒左右

比较与总结

  1. 上面两个其实都不太公平,因为我的C语言代码是在WSL2里面运行的,cpu都是有损耗的情况下。跑出个0.19秒。
  2. 上面的python代码我是直接使用anaconda环境跑的。跑出个1.5秒左右。
  3. 基本上C语言的运行时间是python的10倍左右。
  4. 其实大家如果直接看上面的C代码,发现好像C语言代码也没那么难读。C语言的语法看着还挺现代的。

下图是各个版本的python和C语言的运行效率对比:C语言基本上是要比python快个10倍左右。

其实在科学计算领域,目前最火的就是python和C++。那如果真的是两个都会,确实就无敌了!

不多说了,我去学习C++了!

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 10
    评论
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

yuanzhoulvpi

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值