коллапс эффективного цикла - PullRequest
1 голос
/ 22 января 2010

в некоторых приложениях мне нужно сворачивать вложенные циклы в один, сохраняя при этом индивидуальную информацию индекса.

for j in N:
  for i in M:
    ... A(i,j) ...

// Collapse the loops
for ij in MN:
  ... A(i,j) ...

, поэтому мы рассмотрели очевидные способы восстановления i, j из ij, используя деление / по модулю (дорогая операция) и использование операторов if (векторизация прерываний, проблемы прогнозирования ветвлений). В конце концов, я придумал следующее (используя C в стиле сравнения):

j += (i == m)
i *= (i != m)
++i, ++ij

возможно, есть еще лучший способ сделать это? спасибо

Ответы [ 2 ]

7 голосов
/ 22 января 2010

В общем, он предлагает нет преимущества в производительности, чтобы свернуть цикл, как описано.

Компиляторы иногда сворачивают такие циклы, но обычно непредсказуемым образом.

На определенных языках или на определенных платформах вы можете ускорить циклы в целом:

  • считая вниз
  • делает функцию, вызываемую в теле, «встроенной», или содержит код в теле цикла, а не отдельную функцию
  • настройка компилятора - обычно с помощью параметров командной строки - для «разворачивания» циклов и удаления указателей на фреймы и тому подобное

Но во всех случаях вы должны профилировать свой код, чтобы увидеть, что такие усилия оправданы.

Вообще-то, по моему опыту, во вложенных циклах, подобных этому, преобладают:

  1. контейнеры; по возможности избегайте проверки бокса и границ, и вы знаете, что вы в безопасности
  2. стоимость вызова других методов в них; используйте 'inline', если это доступно
  3. трубопроводные киоски из-за плохой привязки; переставьте вашу память, если это возможно
  4. трубоукладчики по вторым условиям; меньше ifs и косвенных ссылок лучше

Но это может быть неприменимо для вашей проблемной области и платформы. Профиль !

0 голосов
/ 22 января 2010

Другой путь может быть дешевле.

for j in N:
  for i in M:
    ij=j*i+j
...