为什么 Docker 中的算术运算速度较慢?
Why are arithmetic operations slower in Docker?
我有一个简单的程序来测量浮点乘法(和随机生成,编译 g++ -O0)。
当 运行 在主机上(Ubuntu 16.04)它给出每 10000000 次乘法约 1.6 秒,当 运行 在来自图像的容器中 'ubuntu'(没有重新编译)它给出 ~3.6秒。
有人可以解释为什么它会慢 2.5 倍吗?
p.s。我有多个 运行 程序来消除异常值。我不需要优化它,只是详细解释那里发生了什么。
test.cpp
#include <cstdio>
#include <math.h>
#include <chrono>
using namespace std;
using namespace std::chrono;
// timer cribbed from
// https://gist.github.com/gongzhitaao/7062087
class Timer
{
public:
Timer() : beg_(clock_::now()) {}
void reset() { beg_ = clock_::now(); }
double elapsed() const
{
return duration_cast<second_>(clock_::now() - beg_).count();
}
private:
typedef high_resolution_clock clock_;
typedef duration<double, ratio<1>> second_;
time_point<clock_> beg_;
};
#define randf() ((double)rand()) / ((double)(RAND_MAX))
double warmup(Timer tmr) {
tmr.reset();
for (int i = 0; i < 100000000; i++)
{
double r1 = randf();
double r2 = randf();
}
double elapsed = tmr.elapsed();
return elapsed;
}
double test(Timer tmr) {
double total = 0.0;
tmr.reset();
for (int i = 0; i < 100000000; i++)
{
double r1 = randf();
double r2 = randf();
total += r1*r2;
}
double elapsed = tmr.elapsed();
return elapsed;
}
double avg(double* arr) {
double res = 0.0;
for (int i = 0; i < 10; i++) {
res += *(arr + i);
}
return res / 10;
}
int main()
{
double total;
int total2;
Timer tmr;
double warmup_runs[10];
for (int i = 0; i < 10; i++)
{
warmup_runs[i] = warmup(tmr);
printf("warm - %f\n", warmup_runs[i]);
}
double avg_warmup = avg(warmup_runs);
printf("avg warm - %f\n", avg_warmup);
const int runs = 10;
double result[runs];
for (int i = 0; i < runs; i++)
{
result[i] = test(tmr);
printf("real - %f\n", result[i]);
}
double avg_result = avg(result);
printf("avg real - %f\n", avg_result);
printf("d - %f\n", avg_result - avg_warmup);
}
Docker 文件
FROM ubuntu
WORKDIR /arythmetics
COPY a.out .
编译g++ -O0 test.cpp
到 运行 我在构建后使用的容器内:
docker run -it <container> .bin/bash
.\a.out
更新:
使用 -static
标志编译后,程序 运行 时间在两个环境中相同
还有一个问题,为什么实际上是一样的?是不是应该有一些容器化开销?
您正在从 libc 中调用 rand
函数,它在您的 Docker 容器中的实现方式可能有所不同。
为了获得可靠的结果,请在主机和容器中使用完全相同的 OS 和包版本,或者 link libc 静态地使用如下内容:
g++ -O0 -static-libstdc++ -static-libgcc test.cpp
我有一个简单的程序来测量浮点乘法(和随机生成,编译 g++ -O0)。 当 运行 在主机上(Ubuntu 16.04)它给出每 10000000 次乘法约 1.6 秒,当 运行 在来自图像的容器中 'ubuntu'(没有重新编译)它给出 ~3.6秒。 有人可以解释为什么它会慢 2.5 倍吗?
p.s。我有多个 运行 程序来消除异常值。我不需要优化它,只是详细解释那里发生了什么。
test.cpp
#include <cstdio>
#include <math.h>
#include <chrono>
using namespace std;
using namespace std::chrono;
// timer cribbed from
// https://gist.github.com/gongzhitaao/7062087
class Timer
{
public:
Timer() : beg_(clock_::now()) {}
void reset() { beg_ = clock_::now(); }
double elapsed() const
{
return duration_cast<second_>(clock_::now() - beg_).count();
}
private:
typedef high_resolution_clock clock_;
typedef duration<double, ratio<1>> second_;
time_point<clock_> beg_;
};
#define randf() ((double)rand()) / ((double)(RAND_MAX))
double warmup(Timer tmr) {
tmr.reset();
for (int i = 0; i < 100000000; i++)
{
double r1 = randf();
double r2 = randf();
}
double elapsed = tmr.elapsed();
return elapsed;
}
double test(Timer tmr) {
double total = 0.0;
tmr.reset();
for (int i = 0; i < 100000000; i++)
{
double r1 = randf();
double r2 = randf();
total += r1*r2;
}
double elapsed = tmr.elapsed();
return elapsed;
}
double avg(double* arr) {
double res = 0.0;
for (int i = 0; i < 10; i++) {
res += *(arr + i);
}
return res / 10;
}
int main()
{
double total;
int total2;
Timer tmr;
double warmup_runs[10];
for (int i = 0; i < 10; i++)
{
warmup_runs[i] = warmup(tmr);
printf("warm - %f\n", warmup_runs[i]);
}
double avg_warmup = avg(warmup_runs);
printf("avg warm - %f\n", avg_warmup);
const int runs = 10;
double result[runs];
for (int i = 0; i < runs; i++)
{
result[i] = test(tmr);
printf("real - %f\n", result[i]);
}
double avg_result = avg(result);
printf("avg real - %f\n", avg_result);
printf("d - %f\n", avg_result - avg_warmup);
}
Docker 文件
FROM ubuntu
WORKDIR /arythmetics
COPY a.out .
编译g++ -O0 test.cpp
到 运行 我在构建后使用的容器内:
docker run -it <container> .bin/bash
.\a.out
更新:
使用 -static
标志编译后,程序 运行 时间在两个环境中相同
还有一个问题,为什么实际上是一样的?是不是应该有一些容器化开销?
您正在从 libc 中调用 rand
函数,它在您的 Docker 容器中的实现方式可能有所不同。
为了获得可靠的结果,请在主机和容器中使用完全相同的 OS 和包版本,或者 link libc 静态地使用如下内容:
g++ -O0 -static-libstdc++ -static-libgcc test.cpp