Я работаю над простым API машинного обучения, обслуживаемым Flask ( Github repo ). Пока что мой подход таков:
- При первом запуске приложения у меня есть 2 глобальные переменные
face_obj
и od_obj
, которые загружают модели распознавания лиц (dlib) и обнаружения объектов (YoloV3). Моя цель - сделать это только один раз при запуске приложения, потому что загрузка модели стоит дорого - Затем я запускаю приложение через
app.run(...)
и жду запросов. Я использую Flask 1.0.2
, который, как я понимаю, по умолчанию работает в многопоточном режиме. Это то, что я хочу, чтобы иметь возможность обслуживать запросы одновременно - Затем я жду запросов и в зависимости от переданных параметров запроса (
type=face
или type=object
) Я вызываю .detect()
функцию любого объекта и возвращаю JSON фид того, что было обнаружено.
Проблема, с которой я сталкиваюсь, заключается в том, что мое приложение получает несколько одновременные запросы, скажем, 2 запроса на обнаружение объекта вместе, обнаружение объекта полностью не работает и возвращает неверные результаты. При последовательном вызове все в порядке.
Вот мой основной код ( api.py ):
В начале:
# my two globals
face_obj = FaceRecog.Face()
od_obj = ObjectDetect.Object()
И затем в моем классе обнаружения, основанном на параметрах API, я вызываю обнаружение лица или объекта:
class Detect(Resource):
@jwt_required
def post(self):
args = parse_args()
if args['type'] == 'face':
m = face_obj
g.log.debug ('Face Recognition requested')
elif args['type'] in [None, 'object']:
m = od_obj
g.log.debug ('Object Recognition requested')
else:
abort(400, msg='Invalid Model:{}'.format(args['type']))
fip,ext = get_file(args)
fi = fip+ext
image = cv2.imread(fi)
detections = m.detect(image)
return detections
код обнаружения - это стандартные python оболочки обнаружения, использующие OpenCV или dlib's python обертка.
Я не понимаю, почему обнаружение искажается. Насколько я понимаю, когда я запускаю потоки, потоки автоматически создают копии объектов, поэтому не должно быть причин для повреждения.
Я связался с полным проектом выше, если это поможет.
Я читал в другом месте на SO ( Являются ли глобальные переменные потокобезопасными в flask? Как я могу обмениваться данными между запросами? ), что глобалы не являются потоко-безопасными в Flask поэтому я должен преобразовывать мои face_obj
и od_obj
экземпляры в переменные сеанса? Судя по прочтению этой цепочки, возникает вопрос, как разделить / повлиять на данные между потоками. В моем случае я не хочу, чтобы потоки меняли данные. Я просто хочу передать модель one-time-load
нескольким запросам обнаружения.