1

我正在开发在线法官代码检查器。我的代码在 python 2.7 中使用多线程。我的本地机器(我的核心 3 RAM 4GB)上的相同程序在 1 分 10 秒内评估了大约 1000 次提交。但是当我在 ec2 微型实例(大约 600 MB RAM)上运行它时,大约需要 40 分钟(随机几秒钟会变慢)。要知道我把事情搞砸的原因。

  1. 首先这是我的评估员的工作方式:

    • 我有一个主程序worker.py,它创建多个线程
    • 主线程从文件(暂时)中提取提交(一次 10 个)并将它们放入全局队列中
    • 侧线程从队列中获取提交(一个提交仅由一个线程评估)
    • 侧线程接受提交后,将其发送到一个函数compile,该函数将提交的可执行文件返回给该线程
    • 然后线程将此可执行文件发送到run运行可执行文件的函数(使用具有定义的内存和时间限制的沙箱)并将可执行文件的输出写入文件,然后
      根据标准输出检查它
    • 队列变空后,主线程再次拉取 10 个提交并将它们放入队列

  2. 功能compilerun

    • compile 函数和 run 函数将可执行文件和输出分别保存在名为 like的文件中<thread_Name>.exe<thread_Name>.txt这样每个线程都有自己的文件,不会出现覆盖问题。
    • 仅当编译函数的状态正常(已编译的文件)时,线程才会运行函数,否则该提交会引发编译错误

  3. 现在我有疑问:

    • ec2 上执行缓慢的问题是由于它拥有的资源还是由于 python 的多线程。在我的脚本中,线程访问全局变量,例如队列(我放锁),test.py(I dont put lock on it)并且在运行函数中检查输出标准输出字符逐个字符(vimdiff 之类),以及mysandbox.py(libsandbox the sandbox) 其他一些全局变量。由于 python 的 GIL,工作缓慢也是如此。如果是这样,那么为什么它在我的本地机器上工作得很快。
    • 另外暂时我给同一个文件test.cpp(adds two numbers and prints result) 1000次。所以当我故意在这个文件中产生编译错误并在ec2上运行我的主程序时,它运行得非常快。由此我推断出编译和运行(编译和运行函数) 我的程序占用主要时间,而不是线程创建和管理。

我知道这是一个很大的问题,但任何帮助都非常感谢(或者我将不得不继续悬赏它,赌上我所有的声誉:))。

4

1 回答 1

2

对于持续的计算任务(通过设计),微实例变得非常缓慢。

您将代码编写为多线程,以利用整个“机器”的 CPU 资源来执行文件检索和编译等任务,这是提高性能的好习惯。

虽然这在您保证预置硬件资源的物理机或虚拟机上是有意义的,但由于 Amazon 分配资源的方式,它在微实例上没有意义。

根据 Amazon 的文档,微实例仅设计用于短突发 CPU 操作,因此如果您尝试使用占用 CPU 使用率的多个线程,则会遇到 Amazon 本身施加的巨大瓶颈:

如果应用程序消耗的 CPU 资源超过您的实例分配的 CPU 资源,我们会暂时限制该实例,使其在低 CPU 级别运行。如果您的实例继续使用其分配的所有资源,其性能将会下降。我们将增加限制其 CPU 级别的时间,从而增加允许实例再次爆发之前的时间。

查看我刚刚链接到的文档中的 CPU 使用情况图表以获取更多详细信息。

为了证明这是问题所在,您可以简单地启动一个小型实例并在其中运行您的判断软件 - 您应该会体验到类似于您的台式机的显着改进。

TL;DR 当尝试在微型实例上使用持续 CPU 时,它可能会变得不如旧的 Palm Treo 强大。

于 2013-07-04T22:45:06.330 回答