【问题标题】:NodeJS is faster than D when computing prime numbers. How?在计算素数时,NodeJS 比 D 快。如何?
【发布时间】:2014-12-14 14:09:41
【问题描述】:

我在 D 中编写了一个计算素数的简单函数。我认为它非常快,可以计算高达 100,000 的素数。但后来我想将它与 NodeJS 进行比较。当我第一次运行 NodeJS 脚本时,我对差异感到震惊,并仔细检查了我并没有跳过某种计算。但两者在功能上几乎相同。

D:

import std.stdio;
import std.math;
import std.datetime;
import std.file;
import std.array;

enum size_t ITERATIONS = 100_000;

bool divisible(real n) {
    real d;
    for(d = 3; d < floor(n / 2); d += 2) {
        if(n % d == 0) {
            return true;
        }
    }

    return false;
}

void main() {
    StopWatch sw;
    size_t T = ITERATIONS;
    size_t C = 0;
    real n = 2;
    real r[ITERATIONS];
    r[C] = n;
    sw.start();
    C++;
    for(n = 3; n < T; n += 2) {
        if(!divisible(n)) {
            r[C] = n;
            C++;
        }
    }

    sw.stop();
    double seconds = cast(double)sw.peek().usecs / 1_000_000;
    writeln("\n\n", C, " prime numbers calculated in ", seconds, " seconds.");


    File file = File("primes.txt", "w");
    file.writeln("\n", C, " prime numbers calculated ", seconds, " seconds.");

    foreach(number; r[0..C]) {
        file.writeln(number);
    }

    file.writeln("\n", "end");
    file.close();
}

NodeJS:

var fs = require('fs');

var ITERATIONS = 100000;

function divisible(n) {
    var d;
    for(d = 3; d < Math.floor(n / 2); d += 2) {
        if(n % d == 0) {
            return true;
        }
    }

    return false;
}

(function() {
    var buffer  = [ ],
        now     = Date.now(),
        C       = 0
        n       = 2
        ;

    buffer.push(n);
    C++;
    for(n = 3; n < ITERATIONS; n += 2) {
        if(!divisible(n)) {
            buffer.push(n);
            C++;
        }
    }

    var time    = Date.now() - now,
        seconds = time / 1000
        ;

    console.log("\n\n", C, " prime numbers calculated. Process took ", seconds, " seconds.");
    buffer.push("\n" + C + " prime numbers calculated. Process took " + seconds + " seconds.");

    fs.writeFile("node_primes.txt", buffer.join("\n"), function(err) {
        if(err) throw err;

        console.log("Primes have been written to file.");   
    });
})();

结果:

Calculating 100,000 primes:
D:      3.49126 seconds
NodeJS: 0.652 seconds

谁能解释为什么会这样?

提前致谢。

【问题讨论】:

  • D 的编译器和命令行?
  • 我使用dmd /path/to/source.d编译。
  • 试试dmd -O -release -inline -boundscheck=off /path/to/source.d
  • 问题是,D 中的秒表不是在计时文件的写入,而是在实际计算。 Node 脚本也是如此,它不会对文件 IO 进行计时,而只是计算。
  • dmd 的浮点优化器非常糟糕。整数优化器非常好,但浮点/双精度/实数根本没有优化好。使用 gdc 可能会加快速度,或者使用 dmd 切换到 int 也可能会产生很大的不同。

标签: node.js performance time d primes


【解决方案1】:

通过将变量不必要地声明为real,您在可以使用整数运算的情况下强制使用浮点运算。将所有real 实例替换为int,去掉floor(),您的D 程序将与Node.JS 版本一样快:

import std.stdio;
import std.math;
import std.datetime;
import std.file;
import std.array;

enum size_t ITERATIONS = 100_000;

bool divisible(int n) {
    int d;
    for(d = 3; d < n / 2; d += 2) {
        if(n % d == 0) {
            return true;
        }
    }

    return false;
}

void main() {
    StopWatch sw;
    size_t T = ITERATIONS;
    size_t C = 0;
    int n = 2;
    int r[ITERATIONS];
    r[C] = n;
    sw.start();
    C++;
    for(n = 3; n < T; n += 2) {
        if(!divisible(n)) {
            r[C] = n;
            C++;
        }
    }

    sw.stop();
    double seconds = cast(double)sw.peek().usecs / 1_000_000;
    writeln("\n\n", C, " prime numbers calculated in ", seconds, " seconds.");


    File file = File("primes.txt", "w");
    file.writeln("\n", C, " prime numbers calculated ", seconds, " seconds.");

    foreach(number; r[0..C]) {
        file.writeln(number);
    }

    file.writeln("\n", "end");
    file.close();
}

【讨论】:

  • 那一定是命中注定。我在 Node.js 上尝试了该代码并获得了大约 1.8 的加速。
  • 嗨,解决了。我不知道使用 real 会强制使用浮点运算。但有趣的是,从 NodeJS 中删除 Math.floor() 会导致它的运行速度平均慢 0.12 秒..
  • D中的real被定义为精度最高的浮点类型。这意味着它可能是您可以选择的最慢的数字类型。另一方面,V8 运行时可能会对数字运算进行优化。例如,当已知使用整数时,它可能会使用整数运算。
  • @E_net4,我明白了,我使用了 real,因为这是 floor 函数使用的变量类型。我只是没有意识到它[可能]是我可以使用的最慢的类型哈哈。好吧,我们都必须以一种或另一种方式学习。
  • @E_net4 不知何故我没有看到“积极”的部分。猜猜它仍然可以作为您评论的补充。
猜你喜欢
  • 2014-03-26
  • 2018-07-08
  • 2014-07-13
  • 2014-02-27
  • 1970-01-01
  • 2017-05-31
  • 2019-09-09
  • 1970-01-01
  • 2016-02-01
相关资源
最近更新 更多