MATLAB类常量的性能

时间:2018-11-21 15:43:38

标签: matlab class-constants

我的代码中有几个辅助函数,这些给定的数值计算会多次调用该函数。这些辅助函数使用一些常量值进行计算。多个辅助函数可能会使用相同的常数值。

对于define class properties with constant values,这似乎是理想的方案。但是,我已经进行了一些基准测试,结果令我非常惊讶。

请考虑以下类,例如(Consts.m):

classdef Consts
    properties (Constant)
        A = 0.5
        B = 3
    end

    properties
        VariableA
        VariableB
    end

    methods
        function obj = Consts()
            obj.VariableA = 0.5;
            obj.VariableB = 3;
        end
    end
end

以及以下文件(speed_tests.m):

function speed_tests()
    tic;
    for i = 1:200000
        direct_constant_access(1, 2);
    end
    fprintf('Direct constant access: ');
    toc;

    tic;
    c = Consts();
    for i = 1:200000
        passing_extra_obj(1, 2, c);
    end
    fprintf('Passing extra object: ');
    toc;

    tic;
    for i = 1:200000
        persistent_constants(1, 2);
    end
    fprintf('Persistent constants: ');
    toc;

    % Let's assume this code is executed at some point externally:
    % global A B;
    % A = 0.5;
    % B = 3;
    tic;
    for i = 1:200000
        defined_globally(1, 2);
    end
    fprintf('Defined globally: ');
    toc;

    tic;
    for i = 1:200000
        hardcoded(1, 2);
    end
    fprintf('Hardcoded: ');
    toc;

    tic;
    for i = 1:200000
        hardcoded_v2(1, 2);
    end
    fprintf('Hardcoded v2: ');
    toc;
end

function val = direct_constant_access(a, b)
    val = (a + Consts.A)^2 + log(b * Consts.B);
end

function val = passing_extra_obj(a, b, obj)
    val = (a + obj.VariableA)^2 + log(b * obj.VariableB);
end

function val = persistent_constants(a, b)
    persistent A B;
    if isempty(A)
        A = Consts.A^2;
        B = Consts.B;
    end
    val = (a + A)^2 + log(b * B);
end

function val = defined_globally(a, b)
    global A B;
    val = (a + A)^2 + log(b * B);
end

function val = hardcoded(a, b)
    val = (a + 0.5)^2 + log(b * 3);
end

function val = hardcoded_v2(a, b)
    A = 0.5;
    B = 3;
    val = (a + A)^2 + log(b * B);
end

当我在MATLAB R2010b上运行speed_tests()时,这就是我所获得的(您的里程可能会有所不同):

>> speed_tests()
Direct constant access: Elapsed time is 5.973690 seconds.
Passing extra object: Elapsed time is 1.760897 seconds.
Persistent constants: Elapsed time is 1.594263 seconds.
Defined globally: Elapsed time is 1.559441 seconds.
Hardcoded: Elapsed time is 0.673995 seconds.
Hardcoded v2: Elapsed time is 0.661189 seconds.

也许我也很习惯其他编程语言(在编译时,真正的常数可能会被文字直接替换),但是在MATLAB中访问类常数真的很慢吗?还是我错过了什么?

当我在MATLAB R2013a(同一台计算机)上尝试相同的操作时,这种直接常量访问似乎已经有了很大的改进:

>> speed_tests()
Direct constant access: Elapsed time is 2.168146 seconds.
Passing extra object: Elapsed time is 1.593721 seconds.
Persistent constants: Elapsed time is 2.302785 seconds.
Defined globally: Elapsed time is 1.404252 seconds.
Hardcoded: Elapsed time is 0.531191 seconds.
Hardcoded v2: Elapsed time is 0.493668 seconds.

不过,所有非硬编码版本都没有一个接近硬编码版本。这是我可以使用的仅有的两个MATLAB版本,因此我不知道这些年来情况是否一直在改进(并且这对我自己来说并不重要,因为无论如何我都无法使用较新的版本)。

CPU时间是我正在开发的内容的重要因素,但是如果可以的话,我想避免用硬编码的文字填充代码。类不是常量,可以避免这种情况吗?

还有什么我可以考虑的吗?

注意:每次都会使用不同的参数调用真正的辅助函数,因此对我而言,缓存结果无济于事。

1 个答案:

答案 0 :(得分:2)

如果有一种减少访问我也很想知道的类对象的开销的技巧,我也遇到了这个问题。

当我可以的时候,我尽量减少访问对象的次数。在您的示例中,我将在开始循环之前访问A和B一次,然后将它们作为参数传递给每个函数调用。

function speed_tests()
    tic;
    A = Consts.A;
    B = Consts.B;
    for i = 1:200000
        passing_arguments(1, 2, A, B);
    end
    fprintf('Passing arguments: ');
    toc;

    tic;
    for i = 1:200000
        persistent_constants(1, 2);
    end
    fprintf('Persistent constants: ');
    toc;

    tic;
    for i = 1:200000
        hardcoded(1, 2);
    end
    fprintf('Hardcoded: ');
    toc;    
end

function val = passing_arguments(a, b, A, B)
    val = (a + A)^2 + log(b * B);
end

function val = persistent_constants(a, b)
    persistent A B;
    if isempty(A)
        A = Consts.A^2;
        B = Consts.B;
    end
    val = (a + A)^2 + log(b * B);
end

function val = hardcoded(a, b)
    val = (a + 0.5)^2 + log(b * 3);
end

输出:

Passing arguments: Elapsed time is 0.035402 seconds.
Persistent constants: Elapsed time is 0.208998 seconds.
Hardcoded: Elapsed time is 0.027781 seconds.
相关问题