2013-04-17 6 views
11

я с удивлением обнаружил следующую разницу стоимости между запуском MATLAB для петель:Наилучшая практика MATLAB для индекса петли

ksize = 100; 
klist = 1:ksize; 

tic 
for m = 1:100000   
    for k = 1:ksize 

    end   
end 
toc 

tic 
for m = 1:100000   
    for k = klist 

    end   
end 
toc 

Единственная разница в том, как этот список индекс создается. Я бы заподозрил, что вторая версия будет быстрее, но вот!

Elapsed time is 0.055400 seconds. 
Elapsed time is 1.695904 seconds. 

Мой вопрос имеет два аспекта: то, что несет ответственность за выше результата, и где еще делает этот нюанс (или подобные им) происходят в программировании MATLAB? Я надеюсь, что смогу лучше определить эти неэффективности в будущем. Спасибо всем.

+3

Возможно, это связано с ускорением JIT, потому что если вы отключите его с помощью функции ускорения, вы получите аналогичные результаты для обоих прогонов. –

ответ

4

Документация в for() состояниях:

for index = values 
    ... 
end 

values где имеет одну из следующих форм:

  • ...

  • valArray: создает вектор-столбец индекса из последующих столбцов массива valArray на каждый итерация. Например, на первой итерации, index = valArray(:,1). Цикл выполняется для максимум n раз, где n - это количество столбцов valArray, данное numel(valArray, 1, :). Вход valArray может быть любого типа данных MATLAB, включая строку, массив ячеек или структуру.

Поэтому я предполагаю, что существует значительная накладных и компилятор не проверяет, является ли 1:ksize == klist использовать более быструю реализацию. Другими словами, в комментарии Eitan, JIT применяется к первым двум типам принятых значений .

Вся проблема связана со следующей задачей индексации (столбец против элемента):

tic 
for m = 1:100000   
    for k = 1:ksize 
     klist(:,k); 
    end   
end 
toc 

tic 
for m = 1:100000   
    for k = 1:ksize 
     klist(k); 
    end   
end 
toc 

Index column: ~2.9 sec 
Index element: ~0.28 sec 

Вы можете увидеть, как klist(:,k) эффективно замедляет быстрее цикл, указывающий, что проблема в for k = klist связана с индексацией столбца используется в этом случае.

Для получения дополнительной информации см. Это lengthy discussion on (inefficient) indexing.

2

Ответ на этот вопрос - спекуляция (потому что только ребята Mathworks знают о реализации своего продукта), но я думаю, что первый цикл k оптимизирован, чтобы не создавать фактический массив индексов, а просто сканировать их по одному, потому что он явно показывает, как значения «построены». Второй цикл k не может быть оптимизирован, потому что интерпретатор заранее не знает, будет ли содержание массива индексов равномерно расти. Итак, каждый раз, когда начинается цикл, будет копией доступ к оригиналу klist, и поэтому у вас есть штраф за исполнение.

Позже отредактировано: Еще одно ограничение производительности может быть связано с индексированным доступом в массиве klist по сравнению с созданием значений индекса «на лету».

+0

Интересно, можете ли вы проверить это, создав класс, который происходит из 'double' и переопределяет' copy' ... – wakjah

+0

@wakjah Проверено, и дело не в копировании (на самом деле копирования не происходит - я думаю, что копирование -write все еще работает). Речь идет о индексированной ссылке в 'klist'. Я исправил сообщение mt. Спасибо за идею. – 2013-04-17 12:31:37

+0

@wakjah С другой стороны, 'copy' работает над подклассами дескрипторов, и одно не может наследовать классы значений * и * в то же время (на уровне не в R2010a, который у меня есть). Интересно, действительно ли я что-то переопределял ...: D – 2013-04-17 12:37:49

Смежные вопросы