На PackedArray, ищите советы по их использованию - PullRequest
6 голосов
/ 08 января 2012

Раньше я не использовал PackedArray, но начал изучать их, прочитав некоторые обсуждения по ним здесь сегодня.

У меня много больших 1D и 2D матриц всех реалов, и нетсимвольным (это решатель PDE с конечными разностями), и поэтому я подумал, что мне следует воспользоваться PackedArray.

У меня есть функция инициализации, в которой я размещаю все необходимые данные / сетки.Поэтому я пошел и использовал ToPackedArray на них.Кажется, это немного быстрее, но мне нужно больше тестировать производительность, чтобы лучше сравнивать скорость до и после, а также сравнивать использование ОЗУ.

Но, глядя на это, я заметил, что некоторые операции в M автоматически возвращаютсясписки в PackedArray уже есть, а некоторые нет.

Например, этот не не возвращает упакованный массив

a = Table[RandomReal[], {5}, {5}];
Developer`PackedArrayQ[a]

Но этот делает

a = RandomReal[1, {5, 5}];
Developer`PackedArrayQ[a]

и это делает

a = Table[0, {5}, {5}];
b = ListConvolve[ {{0, 1, 0}, {1, 4, 1}, {0, 1, 1}}, a, 1];
Developer`PackedArrayQ[b]

, а также умножение матриц делает возвращает результат в упакованном массиве

a = Table[0, {5}, {5}];
b = a.a;
Developer`PackedArrayQ[b]

Но поэлементное умножение не

b = a*a;
Developer`PackedArrayQ[b]

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

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

спасибо,

update (1)

Просто хотел упомянуть, что обнаружил, что символы PackedArray не допускаются в демонстрационном CDF, так как я получил ошибку при загрузке одного с одним.Итак, пришлось удалить весь мой упаковочный код.Поскольку я в основном пишу демоверсии, сейчас эта тема представляет для меня академический интерес.Но хотел поблагодарить всех за время и хорошие ответы.

Ответы [ 3 ]

9 голосов
/ 08 января 2012

Нет исчерпывающего списка.Отметим несколько вещей:

  • Основные операции с упакованными массивами будут иметь тенденцию оставаться упакованными:
    In[66]:= a = RandomReal[1, {5, 5}];

    In[67]:= Developer`PackedArrayQ /@ {a, a.a, a*a}

    Out[67]= {True, True, True}
  • Обратите внимание, что мойверсия (8.0.4) не распаковывается для поэлементного умножения.

  • Будет ли Table приводить к упакованному массиву, зависит от количества элементов:

    In[71]:= Developer`PackedArrayQ[Table[RandomReal[], {24}, {10}]]

    Out[71]= False

    In[72]:= Developer`PackedArrayQ[Table[RandomReal[], {24}, {11}]]

    Out[72]= True

    In[73]:= Developer`PackedArrayQ[Table[RandomReal[], {25}, {10}]]

    Out[73]= True
  • On["Packing"] включит сообщения, чтобы вы знали, когда что-то распаковывается:
    In[77]:= On["Packing"]

    In[78]:= a = RandomReal[1, 10];

    In[79]:= Developer`PackedArrayQ[a]

    Out[79]= True

    In[80]:= a[[1]] = 0 (* force unpacking due to type mismatch *)

       Developer`FromPackedArray::punpack1: Unpacking array with dimensions {10}. >>

    Out[80]= 0
  • Операции, выполняемые для каждого элементапроверка обычно распаковывает массив,
    In[81]:= a = RandomReal[1, 10];

    In[82]:= Position[a, Max[a]]

       Developer`FromPackedArray::unpack: Unpacking array in call to Position. >>

    Out[82]= {{4}}
  • Там штраф за вызов ToPackedArray в уже упакованном списке достаточно мал, чтобы я не слишком беспокоился об этом:

    In[90]:= a = RandomReal[1, 10^7];

    In[91]:= Timing[Do[Identity[a], {10^5}];]

    Out[91]= {0.028089, Null}

    In[92]:= Timing[Do[Developer`ToPackedArray[a], {10^5}];]

    Out[92]= {0.043788, Null}

  • Интерфейс предпочитает упаковывать неупакованные массивы, которые могут отображаться при работе с Dynamic и Manipulate:
    In[97]:= Developer`PackedArrayQ[{1}]

    Out[97]= False

    In[98]:= Dynamic[Developer`PackedArrayQ[{1}]]

    Out[98]= True
  • При взгляде на производительность сосредоточьтесь на случаях, когда большие списки распаковываются, а не на маленьких.Если только маленькие не находятся в больших петлях.
7 голосов
/ 08 января 2012

Это просто дополнение к ответу Бретта :

SystemOptions["CompileOptions"]

даст вам длину, для которой функция вернет упакованный массив. Поэтому, если вам нужно упаковать небольшой список, в качестве альтернативы использованию Developer`ToPackedArray вы можете временно установить меньшее число для одного из параметров компиляции. например,

SetSystemOptions["CompileOptions" -> {"TableCompileLength" -> 20}]

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

f = # + 1 &;
g[x_] := x + 1;
data = RandomReal[1, 10^6];

On["Packing"]
Timing[Developer`PackedArrayQ[f /@ data]]
{0.131565, True}


Timing[Developer`PackedArrayQ[g /@ data]]
Developer`FromPackedArray::punpack1: Unpacking array with dimensions {1000000}.
{1.95083, False}
4 голосов
/ 08 января 2012

Еще одно дополнение к ответу Бретта: если список является упакованным массивом, то массив ToPackedArray очень быстрый, так как это проверено довольно рано. Также вы можете найти это ценное:

http://library.wolfram.com/infocenter/Articles/3141/

В целом для числовых вещей обращайтесь к Робу Кнаппу и / или Марку Софрониу.

Когда я разрабатываю числовые коды, я пишу функцию и затем использую On ["Packing"], чтобы убедиться, что все упаковано, что нужно упаковать.

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

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