I'm working on a simple machine learning API being served by Flask (Github repo). My approach so far is:
- When the app first starts, I have 2 global variables,
face_obj
andod_obj
that load face recognition (dlib) and object detection (YoloV3)models. My goal is to do this only once at the start of the app because model loading is expensive - Then, I run the app via
app.run(...)
and wait for requests. I am running Flask1.0.2
which I understand defaults to threaded mode, which is what I want to be able to serve requests concurrently - I then wait for requests, and depending on the query parameters passed (
type=face
ortype=object
) I invoke the.detect()
the function of either object and return a JSON feed of what was detected.
The problem I am facing is when my app receives multiple concurrent requests, say 2 object detection requests together, the object detection completely messes up and returns incorrect results. When invoked sequentially, everything is fine.
Here is my main code (api.py):
At the start:
# my two globals
face_obj = FaceRecog.Face()
od_obj = ObjectDetect.Object()
And then in my detection class, based on API parameters, I invoke either face or object detection:
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
The detection code is standard python detection wrappers using OpenCV or dlib's python wrapper.
I am confused about why detection is getting corrupted. My understanding is that when I launch threads, threads automatically make a copy of objects so there should be no reason for corruption.
I've linked to the complete project above if it helps.
I've read elsewhere on SO (Are global variables thread safe in flask? How do I share data between requests?) that globals are not thread-safe in Flask so should I be converting my face_obj
and od_obj
instances into session variables? Based on reading that thread, it seems the ask is to share/affect data between threads. In my case, I don't want threads changing data. I just want to pass on the one-time-load
model to multiple detection requests.