Есть проблемы с производительностью при определении модулей как части выражения Manipulate и в разделе инициализации? - PullRequest
7 голосов
/ 18 декабря 2011

Я хотел бы спросить, знает ли кто-нибудь о каких-либо проблемах (производительности или иным образом), нужно ли определять / помещать модуль (модули), используемый выражением Manipulate, прямо в самом выражении Manipulate, по сравнению с раздел инициализации, где обычно это делается.

Оба метода работают, но семантика не одинакова, когда речь идет о прямом доступе к манипулированию динамикой из модуля (в отличие от того, что они передаются в качестве аргументов модулю, что на самом деле является лучшим методом, но я пытаюсь кое-что попробовать в настоящее время)

Я не знаю, как эти вещи реализованы, но меня беспокоит, что если я поместу все модули в выражение Manipulate, то Manipulate будет замедляться, когда там много модулей, поскольку каждый раз, когда ему нужно обновить выражение , Mathematica FE отправит в ядро ​​гораздо большее выражение для переоценки / анализа или любого другого правильного термина.

Обновляемое выражение Manipulate теперь стало намного больше, поскольку модули теперь являются частью самого выражения Manipulate, а не в разделе инициализации, и это происходит, даже если некоторые из них могут не вызываться при каждом обновлении.

Чтобы помочь объяснить этот вопрос подробнее, я сделал небольшую диаграмму ниже, чтобы показать, что я имею в виду, сравнивая два метода. Ниже я также поместил небольшие примеры кода, используемые на диаграммах:

enter image description here

код для метода части выражения

Manipulate[
foo[]:=Module[{},
x++
];
ctrl;
foo[],

Button["step",{ctrl++ }],
{{ctrl,0},None},
{{x,0},None},
TrackedSymbols:>{ctrl}

]

код для метода инициализации модуля

Manipulate[
 ctrl;
 foo[],

 Button["step", {ctrl++ }],
 {{ctrl, 0}, None},
 {{x, 0}, None},
 TrackedSymbols :> {ctrl},

 Initialization :>
  {
   foo[] := Module[{},
     x++
     ]
   }
 ]

Вопрос в том, будет ли снижение производительности в методе выражения модулей внутри манипуляции?

примечание добавлено:

Кстати, на моем текущем небольшом демо я НЕ заметил какой-либо разницы в производительности обоих методов, но это просто основано на наблюдении за откликом демо и без точных измерений. Может быть, мое понимание раздела «Инициализация» Манипуляции не всегда было правильным. Из справки написано:

Initialization is an option for Dynamic, DynamicModule, Manipulate, 
and related constructs that specifies an expression to be evaluated when 
the construct is first used or displayed.

И, похоже, возможно, я истолковал это как значение по-другому, чем оно есть.

Может быть, Manipulate всегда оценивал все модули каждый раз как часть своего выражения refresh / update?

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

дополнение 19 декабря 2001 г. 23:00 Я посмотрел на решение мистера Wizard, опубликованное ниже. Из того, что я вижу, глядя на снимок Manipulate, полученный код эквивалентен явному помещению модуля в выражение Manipulate. Вот снимок экрана, показывающий оба метода и полученный код (сгенерированный с помощью функции манипуляции с помощью кнопки опции снимка) для каждого макета. Мы видим, что это тот же код.

Но уловка, которую г-н Волшебник использовал, чтобы позволить функции быть помещенной в Control-> None, которая должна писать просто foo вместо foo[], это то, о чем я бы не подумал. Я всегда думал, что нужно написать foo[]:=Module[...], даже если foo не принимает аргументов. (на самом деле я даже не думал об этом, я просто естественно пишу [] в конце каждого имени функции, даже если не принимает аргументов). Спасибо, что поделились этим трюком.

enter image description here

Ответы [ 2 ]

4 голосов
/ 18 декабря 2011

Я думаю, что это должно быть конкретным приложением. Вы можете вставить выражения Pause[1]; перед foo[]:= в обоих примерах, чтобы подтвердить, что переоценка не выполняется в методе Initialization, а в другом. Вопрос о том, сколько времени требуется для оценки ваших выражений, является тем вопросом, на который вы лучше всего можете ответить. Почему бы вам не поместить все свои определения в большой Do цикл и не потратить время?

Кроме того, хотя я обычно не рекомендовал бы это, так как вы работаете в условиях ограничений, возможно, вы открыты для взлома такого рода:

Manipulate[
  ctrl; foo[],
  Button["step", {ctrl++}],
  {{ctrl, 0}, None},
  {{x, 0}, None},
  {{foo, Module[{}, x++] &}, None},
  TrackedSymbols :> {ctrl}
]
1 голос
/ 20 декабря 2011

Ответ на ваше добавление 19 декабря 2001 г. 23:00 :

Как вы можете видеть на приведенном выше снимке экрана, код не на самом деле тот же. В верхнем примере определение foo равно внутри списка переменных DynamicModule и , а не в теле, где оно будет повторно оцениваться. Я полагаю, это именно то, что вам нужно, не так ли?

Вы писали:

Но уловка, которую г-н Волшебник использовал, чтобы позволить функции быть помещенной в Control-> None, то есть писать просто foo вместо foo [], это то, о чем я бы не подумал. Я всегда думал, что нужно написать foo []: = Module [...], даже если foo не принимает аргументов. (на самом деле я даже не думал об этом, я просто естественно пишу [] в конце каждого имени функции, даже если не принимает аргументов). Спасибо, что поделились этим трюком.

Не пропустите механизм, с помощью которого это работает. (Кстати, я действительно ненавидел писать Module[{} ..., но я скопировал его из вашего кода. Пожалуйста, дайте нам избежать этой конструкции в будущем.)

  1. Обычно правильно использовать форму function[] вместо function, если вы хотите выполнить действие. Хотя это вполне возможно, это противоречит природе и синтаксису Mathematica , чтобы инициировать действие только с именем функции. Это также затрудняет обработку самой функции без запуска оценки.

  2. Вы можете получить описанное выше поведение, используя & без аргументов Slot.

Если мы определим doSomething = Print["Something Done!"] &, мы вызовем его с doSomething[], чтобы напечатать строку. Мы все еще можем написать или передать саму функцию, используя doSomething, не вызывая оценку.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...