关于人工智能:Python-314-会比-C-更快

45次阅读

共计 4820 个字符,预计需要花费 13 分钟才能阅读完成。

Python3.11 的基准测试

Python 是数据迷信(DS)和机器学习(ML)中最罕用的脚本语言之一。依据 PopularitY of Programming Languages,Python 是谷歌搜寻最多的语言。除了它是一种将各种 DS/ML 解决方案整合在一起的优良胶水语言之外,它还有许多其余的库能够对数据做各种各样的事件。

大概在一个月前,咱们失去了新的 Python 年度发行版 – 3.11 版。我对这个新版本感到十分兴奋,因为这个版本的次要特点是速度显著进步。

在各种社交媒体上,咱们曾经看到很多人测试新版本的帖子,他们的测试后果令人震惊。但理解 Python3.11 真正有多快的最好办法是本人运行测试。

在这篇文章中,我将分享我对 Python3.11 的逐渐剖析。所有代码都能够在 Github 上找到。

https://github.com/CYang828/p…

对编程语言进行基准测试一点也不简略。当你读 x 比 y 快时,你应该对后果持狐疑态度。算法的一个实现可能比 x 好,而另一个实现比 y 好。对于咱们的基准测试来说,咱们尽可能的心愿它能简略一些,因为咱们正在用 Python 测试 Python,但咱们可能曾经从语言中抉择了一些影响不大的元素。思考到这一点,我想介绍我用于基准测试的算法:基因组组装算法 DNA K-mers。

基因组组装算法 DNA K-mers。

这个算法的思维很简略,DNA 是一个长串序列,称为核苷酸。在 DNA 中,有 4 种核苷酸以字母 A、C、G 和 T 示意。人类(或者更精确地说是智人)有 30 亿个核苷酸对。例如,人类 DNA 的一小部分可能是:

ACTAGGGATCATGAAGATAATGTTGGTGTTTGTATGGTTTTCAGACAATT

在这个例子中,如果想从这个字符串中抉择任何 4 个间断的核苷酸(即字母),它将是一个长度为 4 的 k -mer(咱们称之为 4 -mer)。以下是从示例中导出的一些 4-mers 示例。

ACTA, CTAG, TAGG, AGGG, GGGA, etc.

对于本文,让咱们生成所有可能的 13-mers。从数学上讲,这是一个置换问题。因而,咱们有 4¹³(=67108864)可能的 13-mers。我用一个简略的算法在 C++ 和 Python 中生成后果。让咱们看看不同 Python 版本和 C++ 的比拟后果。

比照 Python 和 C++ 的后果

Python 不同版本的测试

def K_mer(k: int) -> None:
    def convert(c):
        if c == "A":
            return "C"
        if c == "C":
            return "G"
        if c == "G":
            return "T"
        if c == "T":
            return "A"

    print("开始")

    opt = "ACGT"
    s = ""s_last =""
    len_str = k

    for i in range(len_str):
        s += opt[0]

    for i in range(len_str):
        s_last += opt[-1]

    pos = 0
    counter = 1
    while s != s_last:
        counter += 1
        # 你能够勾销下一行的正文来查看所有的 k-mers.
        # print(s)
        change_next = True
        for i in range(len_str):
            if change_next:
                if s[i] == opt[-1]:
                    s = s[:i] + convert(s[i]) + s[i + 1 :]  # type: ignore
                    change_next = True
                else:
                    s = s[:i] + convert(s[i]) + s[i + 1 :]  # type: ignore
                    break

    # 你能够勾销下一行的正文来查看所有的 k-mers.
    # print(s)
    print("生成 k-mers 的数量: {}".format(counter))
    print("实现!")

下面这个脚本曾经能够运行了,然而咱们心愿应用它来测试 Python 的各种版本,而不仅仅是以后装置(或激活)的版本。测试多个 Python 版本的最简略办法是应用 Docker。Python 保护许多 docker 镜像。当然,所有受反对的版本,也包含一些生命周期完结(EOL)的版本,如 2.7 或 3.2。要应用 Docker,您须要装置它。在 Linux 和 Mac 上绝对容易,在 Windows 上我不太确定,但可能也不难。我倡议只装置 docker CLI,桌面对我来说太臃肿了。要在容器化的 Python 环境中运行本地脚本,请运行:

docker run -it --rm \
  -v $PWD/your_script.py:/your_script.py \
  python:3.11-rc-slim \
  python /yourscript.py

为了自动化各种版本的测试,咱们当然也会应用 Python。这个脚本只需启动一个子过程,以启动具备特定 Python 版本的容器,而后收集后果。没什么特地的:

import time
import argparse


def K_mer(k: int) -> None:
    def convert(c):
        if c == "A":
            return "C"
        if c == "C":
            return "G"
        if c == "G":
            return "T"
        if c == "T":
            return "A"

    print("开始")

    opt = "ACGT"
    s = ""s_last =""
    len_str = k

    for i in range(len_str):
        s += opt[0]

    for i in range(len_str):
        s_last += opt[-1]

    pos = 0
    counter = 1
    while s != s_last:
        counter += 1
        # 你能够勾销下一行的正文来查看所有的 k-mers.
        # print(s)
        change_next = True
        for i in range(len_str):
            if change_next:
                if s[i] == opt[-1]:
                    s = s[:i] + convert(s[i]) + s[i + 1 :]  # type: ignore
                    change_next = True
                else:
                    s = s[:i] + convert(s[i]) + s[i + 1 :]  # type: ignore
                    break

    # 你能够勾销下一行的正文来查看所有的 k-mers.
    # print(s)
    print("生成 k-mers 的数量: {}".format(counter))
    print("实现!")


def run_test(k: int) -> None:
    start_time = time.time()
    K_mer(k)
    print(f"{(time.time() - start_time):.4f} 秒")


def main():
    """Main loop in arg parser."""
    parser = argparse.ArgumentParser()
    parser.add_argument(
        "-k",
        "--k_mer",
        help="DNA 序列长度",
        type=int,
        default=13,
    )

    args = parser.parse_args()

    run_test(args.k_mer)


if __name__ == "__main__":
    main()

运行这些测试时,依据处理器的不同,绝对值会因机器而异(它占用大量 CPU)。以下是最近 7 个次要 Python 版本的后果:

 新版本 Python 3.11 破费了 31.9501 秒.
Python 3.5 破费了 63.3502 秒.(Python 3.11 比它快 98.3%)
Python 3.6 破费了 62.9635 秒.(Python 3.11 比它快 97.1%)
Python 3.7 破费了 57.5806 秒.(Python 3.11 比它快 80.2%)
Python 3.8 破费了 59.0129 秒.(Python 3.11 比它快 84.7%)
Python 3.9 破费了 54.4991 秒.(Python 3.11 比它快 70.6%)
Python 3.10 破费了 47.7407 秒.(Python 3.11 比它快 49.4%)

Python 3.11 的基准测试均匀耗时 6.46 秒。与之前的版本(3.10)相比,这简直快了 37%。十分令人印象粗浅!版本 3.9 和 3.10 之间的差别大致相同,使 3.11 简直快了 70%!把所有的点在下图中画进去。

C++ 的测试

当谈到速度时,咱们总是有一个人说:如果你想要速度,为什么不应用 C。

C is much faster that Python! — that one guy

上面咱们用 C++ 实现下面的 K-mers 算法。

#include <iostream>
#include <string>

using namespace std;

char convert(char c)
{if (c == 'A') return 'C';
    if (c == 'C') return 'G';
    if (c == 'G') return 'T';
    if (c == 'T') return 'A';
    return ' ';
}


int main()
{
    cout << "开始" << endl; 

    string opt = "ACGT";
    string s = "";
    string s_last = "";
    int len_str = 13;
    bool change_next;

    for (int i=0; i<len_str; i++)
    {s += opt[0];
    }

    for (int i=0; i<len_str; i++)
    {s_last += opt.back();
    }

    int pos = 0;
    int counter = 1;
    while (s != s_last)
    {   
        counter ++;
        // You can uncomment the next line to see all k-mers.
        // cout << s << endl;  
        change_next = true;
        for (int i=0; i<len_str; i++)
        {if (change_next)
            {if (s[i] == opt.back())
                {s[i] = convert(s[i]);
                    change_next = true;
                } else {s[i] = convert(s[i]);
                    break;
                }
            }
        }
    }

    // You can uncomment the next line to see all k-mers.
    // cout << s << endl;
    cout << "生成 k-mers 的数量:" << counter << endl;
    cout << "实现!" << endl; 
    return 0;
}

家喻户晓,C++ 是一种编译语言,因而,咱们须要先编译源代码,而后能力应用它。装置了 C++ 的根底软件之后,能够键入:

g++ -o k_mer k_mer.c

编译后,只需运行构建可执行文件。输入应如下所示:

 生成 k-mers 的数量: 67108864    破费工夫: 8.92218 秒
生成 k-mers 的数量: 67108864    破费工夫: 9.01176 秒
生成 k-mers 的数量: 67108864    破费工夫: 8.88735 秒
生成 k-mers 的数量: 67108864    破费工夫: 8.9754 秒 

每个循环均匀须要 8.945 秒来计算。
咱们必须批准这一点,因为它真的很快。只花了 8.945 秒就实现了咱们以前用 Python 编程的雷同循环。让咱们把它作为一条线增加到后面的绘图中,如下图所示。

当初,在对后面的数字进行了长时间的剖析之后,咱们分明地看到了 Python 的发展势头。自版本 3.9 以来,Python 的速度进步了约 35%。Python 开发人员提到,接下来的两个版本将有显著的速度晋升,因而,咱们能够假如这个速度将放弃不变(是的,超级平安的假如)。

当初的问题是,在这种势头失去修改的状况下,Python 何时能力超过 C++ 时代。为此,咱们当然能够应用推断来预测下一个 Python 版本的运行工夫。这些能够在下图中看到:

后果真是太棒了!如果放弃这种迭代的速度,Python 3.14 将比 C++ 更快~

申明

尽管这些 Python3.5 到 Python3.11 的基准测试是无效的,但这种推断当然只是一个玩笑。XKCD 格调的画图也是另一种揭示;-)如果您想在各种 Python 版本上运行这些测试或您本人的测试,能够到 Github 下载代码。Github:https://github.com/CYang828/p…

本文由 mdnice 多平台公布

正文完
 0