Я постараюсь ответить на ваш вопрос на высоком уровне. Отказ от ответственности: я не являюсь экспертом по всему стеку того, что вы описываете, и я бы приветствовал исправления или дополнения от людей, которые это делают.
Я рассмотрю различные компоненты снизу вверх:
TensorFlow Serving - это библиотека для развертывания и размещения моделей TensorFlow в качестве серверов моделей, которые принимают запросы с вводом предсказания модели данных и возврата. Идея состоит в том, чтобы обучать модели с помощью TensorFlow, экспортировать их в формат SavedModel и обслуживать их с помощью TF Serving. Вы можете настроить TF-сервер для приема запросов через HTTP и / или RPC. Одним из преимуществ RPC является то, что сообщение запроса сжимается, что может быть полезно при отправке больших полезных данных, например, с данными изображения.
Flask - это среда разработки Python для написания веб-приложений. Он гораздо более универсален, чем TF Serving, и широко используется для создания веб-сервисов, например, в микросервисных архитектурах.
Теперь комбинация порций Flask и TensorFlow должна иметь смысл. Вы могли бы написать веб-приложение Flask, которое предоставляет пользователю API и вызывает модель TF, размещенную с помощью TF Serving под капотом. Пользователь использует API для передачи некоторых данных ( 1 ), приложение Flask, возможно, преобразует данные (например, оборачивает их в массивы), вызывает TF-сервер, чтобы получить прогноз модели ( 2 ) ( 3 ), возможно, преобразует прогноз (например, преобразует прогнозируемую вероятность, превышающую 0,5, в метку класса 1) и возвращает прогноз пользователю ( 4 ). Вы можете визуализировать это следующим образом:
Gunicorn - это интерфейс шлюза веб-сервера (WSGI), который обычно используется для размещения приложений Flask в производственных системах. Как следует из названия, это интерфейс между веб-сервером и веб-приложением. Когда вы разрабатываете приложение Flask, вы можете запустить его локально, чтобы протестировать его. В производстве Gunicorn запустит приложение для вас.
TF Serving будет размещать вашу модель в качестве функционального приложения. Поэтому вам не нужно gunicorn для запуска приложения TF Server.
Nginx - это настоящий веб-сервер, который будет размещать ваше приложение, обрабатывать запросы извне и передавать их на сервер приложений (gunicorn). Nginx не может напрямую общаться с приложениями Flask, поэтому там есть gunicorn.
Этот ответ также может быть полезен.
Наконец, если вы работаете на облачной платформе, часть веб-сервера, вероятно, будет обработана для вас, поэтому вам нужно будет либо написать приложение Flask и разместить его с gunicorn, либо настроить сервер обслуживания TF ,
Вы правы, второе задание заменяет первое. Это не меняет значение в штучной упаковке.
В вашем примере бокс не используется. Значение (int) хранится как int и не упаковывается.
Нет, бокс по-прежнему сохраняет гарантию неизменности.
Очень коротко: бокс означает создание нового экземпляра ссылочного типа . Если вы знаете это, вы понимаете, что один экземпляр не изменяется при создании другого.
То, что вы делаете с a = 2
, не меняет значение в «рамке», вы создаете новый экземпляр ссылочного типа. Так почему же что-то еще должно измениться?
Вот еще один интересный вариант, который поддерживает комментарии Стефана:
int i = 2;
object a = i; // Boxing
object b = a; // Referencing same address on heap as 'a', b == a
b = i; // New boxing on heap with reference new address, b != a
b по-прежнему равен 1, поскольку b - это ссылка, которая по-прежнему указывает на объект в куче со значением 1. a - 2, поскольку вы присвоили его новому объекту в куче со значением 2.
t2.x равно 3, потому что t и t2 - это две разные ссылки на один и тот же объект в куче.
Я тоже ожидал увидеть b == 2, но это не так, почему? это потому что второй бокс разрушает и заменяет весь (а) -объект в куче?
Нет, не совсем. Он оставляет объект как есть в куче (так как переменная b
также ссылается на него) и создает новый объект для нового значения, на который будет ссылаться переменная a
.
Вы правы, что ваш второй пример не использует бокс. Вы не можете получить доступ к значению в штучной упаковке каким-либо иным способом, кроме как распаковать его, поэтому нет способа изменить упакованное значение.
Даже изменяемая структура, такая как Точка
, не может быть изменена в штучной упаковке. , Чтобы получить доступ к свойствам структуры, вы должны распаковать ее, поэтому вы не можете изменить упакованную структуру на месте.
Я думаю, что ответ на ваш вопрос с распаковкой заключается в следующем: результат преобразования без распаковки является временной переменной (больше подробности: ссылка ).
Я думаю, вы пытались сделать что-то вроде:
object a = new Point(10,10);
object b = new Point(20,20);
a = b;
((Point) b).X = 30; //after this operation also a.X should be 30
Приведенный выше код не скомпилируется - подробности в ссылке выше, и я думаю, что это ответ на ваш вопрос:
Я тоже ожидал увидеть b == 2, но это не так, почему? это потому что второй бокс разрушает и заменяет весь (a) -объект в куче?