NIF实现的素数求解效率

素数求解,兼谈Erlang的性能特性一文中比较了Erlang和Java实现的素数求解效率。

在我的MacBook(Intel Core Duo,2GHz,2GB,Leopard 10.5.8)上,计算1000000以内素数:
Java程序的计算时间大概在2850ms左右。
C程序的计算时间在890ms左右。
Erlang程序的计算时间在3900ms左右

采用NIF方式实现的素数查找,计算时间在900ms左右,效率与C程序的相差无几,确实如愿提高了计算效率。

不过个人觉得像文件操作还是使用Port/Driver比较好的,因为对文件的使用可能是一系列持续的操作过程,文件句柄这样的东西还是比较方便的说,NIF比较适合数学函数这样的简单输入->计算->输出

代码如下:
#include <stdbool.h>
#include <math.h>
#include "erl_nif.h"

static bool _isPrime(int i)
{
    int j;
    int t = sqrt(i) + 1;
    for (j=2; j<=t; ++j) {
        if (i % j == 0)
            return false;
    }   
    return true;
}

static ERL_NIF_TERM findPrime(ErlNifEnv *env, ERL_NIF_TERM nterm)
{
    int n;
    if (!enif_get_int(env, nterm, &n)) {
        return enif_make_badarg(env);
    }
    else {
        int i;
        ERL_NIF_TERM res = enif_make_list(env, 0);
        for (i=2; i<n; ++i) {
            if (_isPrime(i)) {
                res = enif_make_list_cell(env, enif_make_int(env, i), res);
            }
        }
        return res;
    }
}

static ErlNifFunc nif_funcs[] = {
    {"findPrime", 1, findPrime}
};

// 宏第一个参数对应着模块名,会被宏自动转换成字符串
ERL_NIF_INIT(prime, nif_funcs, NULL, NULL, NULL, NULL)

编译:
gcc -O3 -fPIC -bundle -flat_namespace -undefined suppress -fno-common -Wall nifprime.c -o nifprime.so -I/usr/local/lib/erlang/usr/include

-module(prime).
-export([load/0, start/2]).

% 装载Native C
load() ->
     erlang:load_nif("nifprime", 0).

start(M, N) ->
    statistics(runtime),
    L = findPrime(M, 1, N, []),
    {_, T} = statistics(runtime),
    io:format("total running time: ~p ms ~n", [T]),
    io:format("found primes number: ~p~n", [length(L)]).

findPrime(N) ->
%    NIF装载后执行Native C程序,若不装载则执行下面的Erlang程序
    findPrime(a, 1, N, []).

findPrime(_, N, N, L) ->
    L;  
findPrime(a, X, N, L) ->
    case isPrimeInt(X, 2, trunc(math:sqrt(X) + 1)) of
        true -> findPrime(a, X+1, N, [X|L]);
        _ -> findPrime(a, X+1, N, L)
    end;
findPrime(z, _X, N, _L) ->
    findPrime(N).

isPrimeInt(1, _, _) -> false;
isPrimeInt(2, _, _) -> true;
isPrimeInt(X, N, E) when N =< E ->
    case X rem N of
        0 -> false;
        _ -> isPrimeInt(X, N+1, E)
    end;
isPrimeInt(_, _, _) -> true.

你可能感兴趣的:(C++,c,erlang,C#,J#)