Необъяснимая проблема Mathematica 7 DumpSave[]
У меня есть очень большой массив данных изображений с плавающей точкой:
In[25]:= Dimensions[daylightImgd]
Out[25]= {18, 2002, 2989}
In[26]:= daylightImgd[[1, 1]][[1 ;; 10]]
Out[26]= {0.0122293, 0.0104803, 0.0103955, 0.0115533, 0.0118063,
0.0120648, 0.0122957, 0.011398, 0.0117426, 0.0119997}
Я могу сохранить весь этот массив изображений на диск, успешно используя DumpSave a la:
DumpSave["thisWorks.mx", daylightImgd]
Сброс этого гиганта (861 мегафайл) занимает менее 10 секунд. Если я опущу эти образы, a la:
downsample[image_, f_] := Module[{w, h}, h = Dimensions[image][[1]];
w = Dimensions[image][[2]];
Table[image[[i, j]], {i, 1, h, f}, {j, 1, w, f}]]
In[26]:= daylightImgdDown = downsample[#, 4] & /@ daylightImgd;
In[27]:= Dimensions[daylightImgdDown]
Out[27]= {18, 500, 748}
In[28]:= daylightImgdDown[[1, 1]][[1 ;; 10]]
Out[28]= {0.0122293, 0.0118063, 0.0117426, 0.0119349, 0.0109443,
0.0121632, 0.0121304, 0.00681408, 0.0101728, 0.00603242}
Затем внезапно я больше не могу дампсейв; вещь висит и вращается вечно - или, по крайней мере, в течение многих минут, пока я не убью ее, и maxes CPU:
In[31]:= DumpSave["broken.mx", daylightImgdDown]; (* Hangs forever *)
Насколько я могу определить, все так, как оно есть. должно быть: уменьшенные изображения имеют правильные размеры; вы можете построить их с помощью ArrayPlot, и все выглядит отлично; вручную перечисление первой строки выглядит прекрасно. Короче говоря, все выглядит так же, как и с изображениями без понижающей выборки, но на гораздо меньшем наборе данных DumpSave висит.
Помощь?
UPDATE: комментарии к ответу Майкла
Вау. Спасибо за чрезвычайно обстоятельный ответ, который не только ответил на мой вопрос, но и научил меня куче и периферийные вещи тоже.
Для вашей справки, проблема упакованности была немного сложнее, чем просто замена моего нижнего образца[] на один из ваших. Поскольку массив, который я пытался сбросить, представляет собой массив из 18 изображений-3d-массив, другими словами, - и поскольку я применяю понижающую дискретизацию через оператор Map, упакованность 3d-массива ложна (согласно PackedArrayQ), используя любую из ваших перезаписей понижающей выборки.Однако, если я возьму выходные данные этих приложений, а затем упакуйте результирующий 3d массив, затем весь 3d массив будет упакован, и только тогда я смогу его сохранить. Странно, однако, что этот заключительный процесс упаковки, хотя и необходимый для успешного сохранения DumpSave, едва ли изменяет размер, как сообщает ByteCount. Может быть, это проще в коде:
In[42]:= downsample3[image_, f_] :=
Module[{w, h}, h = Dimensions[image][[1]];
w = Dimensions[image][[2]];
Developer`ToPackedArray@Table[image[[i, j]], {i, 1, h, f}, {j, 1, w, f}]]
In[43]:= daylightImgdDown = downsample3[#, downsampleSize] & /@ daylightImgd;
In[44]:= ByteCount[daylightImgdDown]
Out[44]= 53966192
In[45]:= Developer`PackedArrayQ[daylightImgdDown]
Out[45]= False
In[46]:= dd = Developer`ToPackedArray[daylightImgdDown];
In[47]:= Developer`PackedArrayQ[dd]
Out[47]= True
In[48]:= ByteCount[dd]
Out[48]= 53963844
In[49]:= DumpSave["daylightImgdDown.mx", dd]; (* works now! *)
Еще раз, большое спасибо.
1 ответ:
Без фактических данных обоснованное предположение состоит в том, что большой массив
DumpSave
быстро заполняется потому, что это так называемый "упакованный массив", то есть массив чисел с плавающей запятой размером с машину, который имеет очень эффективное представление в Mathematica. Ваша функцияdownsample
(из-за использованияTable
) не возвращает упакованный массив, который намного больше в памяти, потенциально больше, чем даже исходный массив после того, как он был уменьшен в 4 раза.ByteCount
может быть показательно там.Вы можете проверить наличие упакованного массива с помощью
Есть два решения, если моя догадка верна. Один из них должен использоватьPackedArrayQ
и попытайтесь упаковать распакованный массив с помощьюToPackedArray
, оба находятся в контекстеDeveloper
.ToPackedArray
, как показано:downsample[image_, f_] := Module[{w, h}, h = Dimensions[image][[1]]; w = Dimensions[image][[2]]; Developer`ToPackedArray@Table[image[[i, j]], {i, 1, h, f}, {j, 1, w, f}]]
Еще лучше просто заменить использование
Table
наTake
, которое в этом случае должно возвращать упакованный массив, и в качестве дополнительного бонуса будет намного быстрее, чем использованиеTable
.downsample[image_, f_] := Take[image, {1,-1,f}, {1,-1,f}]
Вы также можете быть интересуюсь всеми новыми функциями обработки изображенийв Mathematica 7.
Надеюсь, это поможет!