2013-08-10 1 views
9

Matlab documentation говорит, чтоПодробнее об использовании I и J в качестве переменных в Matlab: скорость

For speed and improved robustness, you can replace complex i and j by 1i. For example, instead of using

a = i; 

use

a = 1i; 

робастности часть ясна, as there might be variables called i or j. Однако, как и для скорости, я сделал простой тест в Matlab 2010b, и я получить результаты, которые кажутся противоречащими претензии:

>>clear all 

>> a=0; tic, for n=1:1e8, a=i; end, toc 
Elapsed time is 3.056741 seconds. 

>> a=0; tic, for n=1:1e8, a=1i; end, toc 
Elapsed time is 3.205472 seconds. 

Любые идеи? Это может быть проблема, связанная с версией?

После комментариев @TryHard и @horchler, я попытался назначить другие значения переменной a, с этими результатами:

Increasing order of elapsed time:

"i" < "1i" < "1*i" (trend "A")

"2i" < "2*1i" < "2*i" (trend "B")

"1+1i" < "1+i" < "1+1*i" (trend "A")

"2+2i" < "2+2*1i" < "2+2*i" (trend "B")

+0

Как насчет более общего случая '2 * i' против' 2i' (или даже '2 * 1i')? – horchler

+0

Я вижу улучшение x 5 с R14 на ноутбуке rinky dink с XP. –

+0

Я бы применил 'clear all' до каждого цикла? –

ответ

9

Я думаю, что вы смотрите на патологический примере. Попробуйте что-то более сложное (Показанные результаты для R2012b на OSX):

(повторное добавление)

>> clear all 
>> a=0; tic, for n=1:1e8, a = a + i; end, toc 
Elapsed time is 2.217482 seconds. % <-- slower 
>> clear all 
>> a=0; tic, for n=1:1e8, a = a + 1i; end, toc 
Elapsed time is 1.962985 seconds. % <-- faster 

(многократное умножение)

>> clear all 
>> a=0; tic, for n=1:1e8, a = a * i; end, toc 
Elapsed time is 2.239134 seconds. % <-- slower 
>> clear all 
>> a=0; tic, for n=1:1e8, a = a * 1i; end, toc 
Elapsed time is 1.998718 seconds. % <-- faster 
+13

«Попробуйте что-то более сложное ...» - надеюсь, я надеюсь. :-) – horchler

+0

Возможно, так оно и есть. Затем, требование «Для скорости и повышенной надежности вы можете заменить сложные i и j на 1i. Например, вместо использования a = i; использование a = 1i» в документации строго неверно –

+1

Для обеспечения надежности документация правильная (например, если вы случайно запускаете 'i = 3', тогда' a = i' будет устанавливать 3, но 'a = 1i' будет по умолчанию сложным' i'), но я согласен, что непонятно, почему они добавили соображения скорости – SheetJS

5

Одна вещь, чтобы помнить о том, что оптимизация применяются по-разному ли вы работаете из командной строки или с сохраненной M-функцией.

Вот испытание мои:

function testComplex() 
    tic, test1(); toc 
    tic, test2(); toc 
    tic, test3(); toc 
    tic, test4(); toc 
    tic, test5(); toc 
    tic, test6(); toc 
end 

function a = test1 
    a = zeros(1e7,1); 
    for n=1:1e7 
     a(n) = 2 + 2i; 
    end 
end 

function a = test2 
    a = zeros(1e7,1); 
    for n=1:1e7 
     a(n) = 2 + 2j; 
    end 
end 
function a = test3 
    a = zeros(1e7,1); 
    for n=1:1e7 
     a(n) = 2 + 2*i; 
    end 
end 

function a = test4 
    a = zeros(1e7,1); 
    for n=1:1e7 
     a(n) = 2 + 2*j; 
    end 
end 

function a = test5 
    a = zeros(1e7,1); 
    for n=1:1e7 
     a(n) = complex(2,2); 
    end 
end 

function a = test6 
    a = zeros(1e7,1); 
    for n=1:1e7 
     a(n) = 2 + 2*sqrt(-1); 
    end 
end 

Результатов на моей машине Windows, под управлением R2013a:

>> testComplex 
Elapsed time is 0.946414 seconds. %// 2 + 2i 
Elapsed time is 0.947957 seconds. %// 2 + 2j 
Elapsed time is 0.811044 seconds. %// 2 + 2*i 
Elapsed time is 0.685793 seconds. %// 2 + 2*j 
Elapsed time is 0.767683 seconds. %// complex(2,2) 
Elapsed time is 8.193529 seconds. %// 2 + 2*sqrt(-1) 

Обратите внимание, что результаты колеблются немного с разными трассами, где порядок звонки перетасовываются. Поэтому возьмите тайминги с солью.

Мое заключение: не имеет значения с точки зрения скорости, если вы используете 1i или 1*i.


одно интересное отличие состоит в том, что если у вас также есть переменная в области видимости функции, где вы также использовать его в качестве мнимой единицы, MATLAB выдает ошибку:

Error: File: testComplex.m Line: 38 Column: 5 
"i" previously appeared to be used as a function or command, conflicting with its 
use here as the name of a variable. 
A possible cause of this error is that you forgot to initialize the variable, or you 
have initialized it implicitly using load or eval. 

Чтобы увидеть ошибку, изменение выше test3 функции в:

function a = test3 
    a = zeros(1e7,1); 
    for n=1:1e7 
     a(n) = 2 + 2*i; 
    end 
    i = rand();  %// added this line! 
end 

т.е. переменная i была использована в качестве как функции и переменной в одной и той же локальной области.

+2

Бьюсь об заклад, если вы «разогреете» эти функции перед их синхронизацией, любые различия исчезнут в шуме. – horchler

+0

Для меня с прогревом или без него результаты были такими же: около 0,43 для первых четырех методов (без существенной разницы), а затем 0,58 и 1,2 соответственно. Выиграл его несколько раз, а последние два значительно медленнее, чем первые четыре. –

+2

правда, способ измерения времени не очень точен. Лучшее решение - использовать [TIMEIT] (http://www.mathworks.com/matlabcentral/fileexchange/18798-timeit-benchmarking-function) из Файлового Exchange, который заботится о том, чтобы разогревать код, запускать его несколько раз , и усредняя результаты, все принимая во внимание накладные расходы на вызывающие функции ... Вы будете рады узнать, что следующая версия MATLAB (предварительная информация о знании) включает эту функцию изначально! – Amro