Могу ли я в Common Lisp выполнять арифметические операции на месте на подсетке?
Я использую Antik
а также Gsll
для матричных расчетов.
Иногда я хочу выполнять арифметические операции над подсетью (например, умножить столбец матрицы на 2,0). Теперь я должен написать эти коды:
(setf (grid:column mat 0) (gsll:elt* (grid:column mat 0) 2.0))
Согласно этим кодам, Antik
сначала нужно создать временную сетку для хранения промежуточных результатов, а затем установить ее в исходное состояние mat
, Создание временной сетки может быть медленным, когда матрица огромна. Поэтому я надеюсь, что смогу сделать это прямо на оригинале mat
,
PS: gsll:elt*
выполняет модификацию всей матрицы на месте, например (gsll:elt* mat 2.0)
и это очень эффективно, даже когда mat
огромный.
Обновить:
Я показываю результат моего эксперимента здесь:
Код:
(let ((mat (grid:make-simple-grid
:grid-type 'grid:foreign-array
:initial-contents
(loop repeat 100 collect
(loop repeat 100 collect
(random 100))))))
(time (loop repeat 1000 do
(gsll:elt* mat 2.0)
(gsll:elt* mat 0.5)))
(time (loop repeat 1000 do
(setf (grid:row mat 0) (gsll:elt* (grid:row mat 0) 2.0))
(setf (grid:row mat 0) (gsll:elt* (grid:row mat 0) 0.5)))))
Результат:
Evaluation took:
0.016 seconds of real time
0.016000 seconds of total run time (0.016000 user, 0.000000 system)
100.00% CPU
46,455,124 processor cycles
353,280 bytes consed
Evaluation took:
0.446 seconds of real time
0.444000 seconds of total run time (0.420000 user, 0.024000 system)
[ Run times consist of 0.008 seconds GC time, and 0.436 seconds non-GC time. ]
99.55% CPU
1,308,042,508 processor cycles
102,275,168 bytes consed
Обратите внимание, что первое вычисление выполняется для всей матрицы 100x100, что даже быстрее, чем второе (только для подматрицы 1x100). А последний расходует гораздо больше байтов из-за выделения временного хранилища.