erlang 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比较适合数学函数这样的简单输入->计算->输出

代码如下:
C代码  收藏代码

    #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) 


编译:
Shell代码  收藏代码

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


Erlang代码  收藏代码

    -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. 

你可能感兴趣的:(erlang)