Julia的执行效率与主流科学计算语言一个简单的对比

Int64是long long吧?

https://en.cppreference.com/w/c/language/arithmetic_types

按照标准,long 这些类型只规定了最低多少位,应该用 stdint.h 里的 int64_tint32_t

#include <stdio.h>
#include <stdint.h>
#define MAX 50000

int prime(int32_t n);

int prime(int32_t n) {
  int32_t i;

  for (i= 2; i < n; i++)
	if (n % i == 0)
	  return 0;

  return 1;
}

int main() {
  int32_t i;

  for (i= 2; i <= MAX; i++) prime(i);

  return 0;
}

这个时候32和64就是有差别的。

我也来凑个热闹。

机子上只有matlab 2018a, python3.6 + numba0.39 + cython0.28.5,vs 2010,其它没有装,主要对比的是numba和cython还有Julia
cpu为i7-4712h

代码稍微改动一下,要不然我的c和numba偷懒不干活,直接跳过去了,不知道是不是main函数循环对结果没影响被优化了。

c:

int main() {
    int i;
    int n = 0;

    for (i= 2; i <= MAX; i++) {
        n += prime(i);
    }
    return n;
}

cython:

cdef int testp(int x):
    cdef int i
    for i in range(2, x):
        if x % i == 0:
            return 0
    return 1

def runme():
    cdef int i
    cdef int n = 0
    for i in range(1, 500000):
        n += testp(i)
    return n

numba:

import numba as nb


@nb.jit(nb.int32(nb.int32), nopython=True)
def testp(x):
    for i in range(2, x):
        if x % i == 0:
            return 0
    return 1


@nb.njit
def runme():
    n = 0
    for i in range(1, 500000):
        n += testp(i)
    return n

Julia:

function testp(x)
    for i=2:x-1
        x % Cint(i) == 0 && return 0
    end
    return 1
end
 
function runme()
    for i = 1:500000
        testp(Cint(i))
    end
 end

C的运行时间是为30.13s
matlab的运行时间是为212.34s
python+cython的运行时间是为37.3s
python+numba的运行时间为43.8s
Julia的运行时间为33.67s
报告完毕!

如果要match数据类型的话,这种比较就显得很不自然了。另外,compilation的选项不清楚以及MATLAB貌似最新版会自动用多核。这种语言之间的速度比较特别难,往往很有争议。

Julia的好处在于语法很friendly, 而且速度可以是scalable。因为大部分速度对比的例子都是code不超过几十行,所以对实际应用implications不大。我这里的scalable是指code量和运算量同时增加,这个时候Julia就很有优势。

ps: Mathematica不是主流科学计算语言。。。。。

纯for loop的写法,compiled language一般占很大优势,Cython和Matlab的mex与C的速度比较差不多就是C和C自己比较。

Julia和Matlab的优势在数学语法的舒适度和性能并存,但说性能好多硬件语言速度要快的多。

你的 c 版本运行快慢也和编译器有关吧。我用 clang,几乎是秒算完。不过你的 julia 版本我电脑上(v0.6.4)要85秒。

那个如果开了优化,C是压根没算。直接结束了。。。你注意一下生成的汇编。。。我这里开了O3就直接结束了。

这些代码我都是按照默认优化跑的。然后Julia都是 1.0版本,1.0比起0.6有很多新的优化(虽然某些性能有regression,但是会随着后面版本的更新慢慢修复)

QQ%E5%9B%BE%E7%89%8720180814181631
如果代码考虑到并行,matlab是很厉害的

不就开个多线程,多大点事儿[doge]

function runme()
    Threads.@threads for i = 1:500000
        testp(Cint(i))
    end
 end
1 个赞

这有点开始歪楼了,OP强调了实验都是单核执行,感觉这贴讨论的差不多了,适当时机可以锁了。这类帖在官方discourse也一样,最后有可能会变成引战贴,后面的内容都不会太有营养。:pensive: :pensive: :pensive: 说实话,Julia用了这么长时间,这类帖子早就看厌了,懒得争。

不好,别用。-- 张实唯

bounds check不是针对数组indexing的么

你说的对,我看错了

C就是直接的gcc -o …
Julia是在Include(“…”)
请问你说的抽象是什么呢?

最后一个不是Python嘛…
我用的Mathematica是11.2

不同编译器对long long的理解不一样的,因为标准只规定了long long 不应该小于int, 你可以试一试sizeof(int)和sizeof(long long).
我觉得差距不大的原因是因为你的编译器理解的这两个类型是一样的

Mathematica不是主流科学计算语言。。。。。

非引战,这个要看领域的吧,学物理的人用Mathematica的比例还是挺多的…

I see…
果然我把类型定在Int32就很快了,跑了40s, 和C(35.6s) 就在一个量级上了

但这似乎同时对其它语言不太公平,matlab是用double在跑? 所以说要做好这种benchmark是挺难的,公平性就很难定义,这也是这类讨论容易引战的原因吧。

是这样的,其实如果裸写循环,或者裸写个cython大家总有办法写出来差不多太多速度的代码。但是当你需要封装出来一个 class (在python里),在Julia里面声明一些抽象类型和类型。这个时候其实才是真正对实际工作有意义的(你总不可能永远用一些Float之类的数值类型搞低抽象吧)。但是这种很难说公平的测试,但是我想说的是目前我们自己的实践是比Python + C++快的。而且不需要C++。当你真的写Python + C++的时候,一些新手其实反而因为没搞清楚CPython的机制,写出效率低的wrapper(我在知乎上也曾经见到有人问为什么自己写的CPython比cython生成的慢)。所以最后大家还是看一个完整的实践比如einsum和另外一个语言里完整的实践比吧。这样对实际的工作更有意义一些。

2 个赞

该主题在创建22小时后自动关闭。不再允许新的回复。