Я подозреваю, что MapList
приближается к пределу производительности для любого преобразования, которое выполняет структурную модификацию.Существующие целевые ориентиры не совсем честные сравнения.Пример Map
создает простой вектор целых чисел.Пример ConstantArray
создает простой вектор общих ссылок на тот же список.MapList
плохо показывает эти примеры, потому что он создает вектор, в котором каждый элемент представляет собой недавно сгенерированную неразделенную структуру данных.
Ниже я добавил еще два теста.В обоих случаях каждый элемент результата представляет собой упакованный массив.Случай Array
генерирует новые элементы, выполняя добавление Listable
к a
.В случае Module
создаются новые элементы путем замены одного значения в копии a
.Эти результаты следующие:
In[8]:= a = Range@1000;
#^2 & /@ a // timeAvg
MapList[#^2 &, a] // timeAvg
ConstantArray[#^2 & /@ a, 1000] // timeAvg
Array[a+# &, 1000] // timeAvg
Module[{c}, Table[c = a; c[[i]] = c[[i]]^2; c, {i, 1000}]] // timeAvg
Out[9]= 0.0005504
Out[10]= 0.0966
Out[11]= 0.003624
Out[12]= 0.0156
Out[13]= 0.02308
Обратите внимание, что новые тесты работают гораздо больше, чем MapList
, а не как Map
или ConstantArray
.Похоже, это показывает, что нет особых возможностей для кардинального улучшения производительности MapList
без некоторой глубокой магии ядра.Мы можем немного сэкономить время с MapList
, таким образом:
MapListWR4[f_, expr_, level_: {1}] :=
Module[{positions, replacements}
, positions = Position[expr, _, level, Heads -> False]
; replacements = # -> f[Extract[expr, #]] & /@ positions
; ReplacePart[expr, #] & /@ replacements
]
, что приводит к следующим временным значениям:
In[15]:= a = Range@1000;
#^2 & /@ a // timeAvg
MapListWR4[#^2 &, a] // timeAvg
ConstantArray[#^2 & /@ a, 1000] // timeAvg
Array[a+# &, 1000] // timeAvg
Module[{c}, Table[c = a; c[[i]] = c[[i]]^2; c, {i, 1000}]] // timeAvg
Out[16]= 0.0005488
Out[17]= 0.04056
Out[18]= 0.003
Out[19]= 0.015
Out[20]= 0.02372
Это соответствует фактору 2 случая Module
, и я ожидаючто дальнейшая микрооптимизация может еще больше сократить разрыв.Но я с нетерпением жду, что я присоединюсь к вам в ожидании ответа, который покажет дальнейшее десятикратное улучшение.