Можно ли использовать в Юлии что-то вроде указателей или ссылок, как в C / C ++ или C #? Мне интересно, потому что будет полезно передавать тяжелые объекты как указатель / ссылку, но не как значение. Например, использование памяти указателей для хранения объекта может быть выделено один раз для всей программы, а затем указатель может быть передан через программу. Как я могу себе представить, это повысит производительность памяти и использование вычислительной мощности.
Простой код на C ++, показывающий, что я пытаюсь выполнить в Джулии:
#include <iostream>
void some_function(int* variable){ // declare function
*variable += 1; // add a value to the variable
}
int main(){
int very_big_object = 1; // define variable
some_function( &very_big_object ); // pass pointer of very_big_object to some_function
std::cout << very_big_object; // write value of very_big_object to stdout
return 0; // end of the program
}
Выход:
2
Создается новый объект, его указатель затем передается в some_funciton, который изменяет этот объект, используя переданный указатель. Возврат нового значения не требуется, поскольку программа редактировала исходный объект, а не копию. После выполнения some_function значение переменной печатается, чтобы увидеть, как оно изменилось.
Хотя вы можете вручную получить указатели на объекты Julia, на самом деле это не обязательно для получения желаемой производительности и результатов. Как указано в руководстве :
следовательно, вы можете просто передать объект функции в обычном режиме, а затем работать с ним на месте. Функции, которые изменяют свои входные аргументы (включая любые функции на месте) по соглашению в Julia, имеют имена, оканчивающиеся на
!
. Единственная загвоздка в том, что вы должны быть уверены, что в теле функции не сделаете ничего, что могло бы вызвать копирование объекта.Так, например
(обратите внимание, в частности, на
.
перед.=
во второй версии; это очень важно. Если бы мы не использовали это, мы фактически не мутировали быA
, а просто переназначили бы имяA
(внутри область действия функции) для ссылки на результат RHS, так что это фактически было бы полностью эквивалентно первой версии, если бы не это.
)Если мы затем протестируем их, вы четко увидите разницу:
Обратите особое внимание на разницу в использовании и распределении памяти в дополнение к разнице во времени ~ 4x. На данный момент практически все время тратится на фактическое добавление, поэтому единственное, что нужно оптимизировать, если это критичный для производительности код, — это убедиться, что код эффективно использует все ваши CPU векторные регистры и инструкции SIMD, которые можно сделать с помощью LoopVectorization.jl:
Это дает нам немного больше производительности, но похоже, что для этого конкретного случая обычный компилятор Джулии, вероятно, уже нашел некоторые из этих оптимизаций SIMD.
Теперь, если по какой-либо причине вам все еще нужен буквальный указатель, вы всегда можете получить его с помощью
Base.pointer
, хотя обратите внимание, что это сопровождается некоторыми существенными оговорками и, как правило, не то, что вам нужно.Хотя Джулия использует передачу по совместному использованию, и обычно вам не нужно / не хотите использовать указатели, в некоторых случаях вы действительно хотите это сделать, и вы можете!
Вы создаете указатели с помощью
Ref{Type}
, а затем уважаете их с помощью[]
. Рассмотрим следующую функцию, изменяющую свой аргумент.Это можно использовать следующим образом:
Для более подробного обсуждения передачи ссылки в Julia, пожалуйста, посмотрите этот пост Как передать объект по ссылке и значению в Julia?