8

我是 Julia 的新手,我编写了一个简单的函数来计算 RMSE(均方根误差)。ratings是一个评分矩阵,每一行是[user, film, rating]. 有 1500 万个收视率。该rmse()方法需要 12.0 秒,但 Java 实现大约快 188 倍:0.064 秒。为什么 Julia 的实现这么慢?在 Java 中,我正在处理一个Rating对象数组,如果它是一个多维int数组,它会更快。

ratings = readdlm("ratings.dat", Int32)

function predict(user, film)
    return 3.462
end

function rmse()
    total = 0.0
    for i in 1:size(ratings, 1)
        r = ratings[i,:]
        diff = predict(r[1], r[2]) - r[3]
        total += diff * diff
    end
    return sqrt(total / size(ratings)[1])
end

编辑:避免全局变量后,它在 1.99 秒内完成(比 Java 慢 31 倍)。删除 后r = ratings[i,:],它是 0.856 秒(慢 13 倍)。

4

3 回答 3

10

几点建议:

  • 不要使用全局变量。由于烦人的技术原因,它们很慢。相反,ratings作为参数传入。
  • r = ratings[i,:]行制作副本,速度很慢。相反,使用predict(r[i,1], r[i,2]) - r[i,3].
  • square()可能比x*x-- 试试看更快。
  • 如果您使用源代码中的前沿 Julia,请查看全新的NumericExtensions.jl,它为许多常见的数值运算提供了疯狂优化的功能。(参见 julia-dev 列表
  • Julia 必须在第一次执行代码时对其进行编译。在 Julia 中进行基准测试的正确方法是多次计时并忽略第一次。
于 2013-06-22T15:13:34.903 回答
7

对我来说,以下代码在 0.024 秒内运行(我怀疑我的笔记本电脑比你的机器快很多)。我用注释掉的行初始化了评级,因为我没有你提到的文件。

function predict(user, film)
    return 3.462
end

function rmse(r)
    total = 0.0
    for i = 1:size(r,1)
        diff = predict(r[i,1],r[i,2]) - r[i,3]
        total += diff * diff
    end
    return sqrt(total / size(r,1))
end

# ratings = rand(1:20, 5000000, 3)
于 2013-06-22T23:13:36.293 回答
5

在我的系统上,问题似乎是您的常量值predict函数没有得到优化。替换多余的调用predict使代码在 0.01 秒内运行。

function time()
    ratings = ones(15_000_000, 3)
    predict(user, film) = 3.462
    function rmse(ratings)
        total = 0.0
        for i in 1:size(ratings, 1)
            diff = predict(ratings[i, 1], ratings[i, 2]) - ratings[3]
            total += diff * diff
        end
        return sqrt(total / size(ratings, 1))
    end
    rmse(ratings)
    @elapsed rmse(ratings)
end

time()

function time2()
    ratings = ones(15_000_000, 3)
    predict(user, film) = 3.462
    function rmse(ratings)
        total = 0.0
        for i in 1:size(ratings, 1)
            diff = 3.462 - ratings[3]
            total += diff * diff
        end
        return sqrt(total / size(ratings, 1))
    end
    rmse(ratings)
    @elapsed rmse(ratings)
end

time2()
于 2013-06-23T03:11:21.660 回答