打包yolov5算法镜像开通接口,长时间压测发现内存缓慢上涨,使用atlas 300i pro显卡
收藏回复举报
打包yolov5算法镜像开通接口,长时间压测发现内存缓慢上涨,使用atlas 300i pro显卡
t('forum.solved') 已解决
新人帖
发表于2024-03-19 20:39:14
0 查看

推理函数

from common.util.dataset import coco80_to_coco91_class, correct_bbox, save_coco_json

from runServer.yolov5.utils.general import non_max_suppression, scale_coords
from runServer.yolov5.utils.datasets import letterbox
def detect_om(model, img, cfg):
    pred_results = []
    height,width,_ = img.shape
    img, ratio, _ = letterbox(img, new_shape=(640, 640),auto = False)
    img = img[:, :, ::-1].transpose(2, 0, 1)  # BGR to RGB, to 3x416x416
    img = np.ascontiguousarray(img)
    #如果是torch张量
    img = torch.from_numpy(img)
    img = img.half()
    #如果是numpy数组
    #img = img.astype(np.float16)

    img /= 255.0  # 0 - 255 to 0.0 - 1.0
    # 确保 img 是四维的
    if len(img.shape) == 3:
        # 如果是 NumPy 数组
        #img = np.expand_dims(img, axis=0)
        # 或者如果是 PyTorch 张量,加一维张量,试batch_size为1
        img = img.unsqueeze(0)
    nb, _, _, _ = img.shape  # batch size, channels, height, width
    #  注意这里的nb指的是batchsize,以上代码将nb写死默认为1,如果转模型更改了batchsize,要在这里对应更改nb

    padding = False
    # batch_size = model.get_inputs()[0].shape[0]
    # if nb != batch_size:
    #     img = np.pad(img, ((0, batch_size - nb), (0,0), (0,0),(0,0)), 'constant', constant_values=0)
    #     padding = True
    # else:
    img = img.numpy()

    # om infer
    old_time = time.time()

    result = model.infer([img])


    #new_time = time.time()
    #print("model.infer时间为%.2f" % (new_time - old_time))
    if len(result) == 3:  # number of output nodes is 3, each shape is (bs, na, no, ny, nx)
        out = []
        for i in range(len(result)):
            anchors = torch.tensor(cfg['anchors'])
            stride = torch.tensor(cfg['stride'])
            cls_num = cfg['class_num']
            if padding == True:
                result[i] = result[i][:nb]
            correct_bbox(result[i], anchors[i], stride[i], cls_num, out)
        box_out = torch.cat(out, 1)
    else:  # only use the first output node, which shape is (bs, -1, no)
        if padding == True:
            result[0] = result[0][:nb]
        box_out = torch.tensor(result[0])

    # non_max_suppression
    boxout = nms(box_out, conf_thres=cfg["conf_thres"], iou_thres=cfg["iou_thres"])

    for idx, pred in enumerate(boxout):
        try:
            #scale_coords(img[idx].shape[1:], pred[:, :4], (height, width), (ratio,x))  # native-space pred
            scale_coords(img[idx].shape[1:], pred[:, :4], (height, width))
            #det[:, :4] = scale_coords(img.shape[2:], det[:, :4], im0.shape).round()
        except:
            pred = torch.tensor([[0.0, 0.0, 0.0, 0.0, 0.0, 0.0]])
        # append to COCO-JSON dictionary
        #path = Path(paths[idx])
        #image_id = int(path.stem) if path.stem.isnumeric() else path.stem
        save_coco_json(pred, pred_results, "111" , coco80_to_coco91_class())
    del (img)
    torch_npu.npu.empty_cache()
    return pred_results

def fireandsmokeDetection_Result_om(image, models,cfg,conf_thres,labelnameDict):
    result_dict = {}
    result_dict["data"] = []
    #old_time = time.time()
    pred_results = detect_om(models, image, cfg)
    #new_time = time.time()
    #print("detect_om时间为%.2f" % (new_time - old_time))
    for i,x in enumerate(pred_results):
        if x["score"] > conf_thres:
            result_dict["data"].append({})
            bbox = list(map(int, x['bbox']))
            # 将左上角点的横坐标和纵坐标改为中间点
            #bbox[0] = int(bbox[0] + bbox[2] / 2)
            #bbox[1] = int(bbox[1] + bbox[3] / 2)
            result_dict["data"][i]["bbox"] = bbox
            #print(x["category_id"])
            #print(labelnameDict[x["category_id"]])
            if x["category_id"] in list(labelnameDict.keys()):
                result_dict["data"][i]["type"] = str(labelnameDict[x["category_id"]])
            result_dict["data"][i]["score"] = float(x["score"])
            result_dict["data"][i]["is_alarm"] = 1
            result_dict["data"][i]["area_id"] = ""
    del(pred_results)

    #torch_npu.npu.empty_cache()
    return result_dict

fastapi接口

from imageRun_fireandsmoke_server_om import fireandsmokeDetection_Result_om
from ais_bench.infer.interface import InferSession
h_model = None
if h_model == None:
    # load custom plugins
    print("加载烟火om版模型")
    h_model = InferSession(0, "/home/css/project/runServer/yolov5/weights/fireandsmoke_bs1_cann6.3.RC2.om")
    #h_model = InferSession(0, "/root/zsh_code/fireandsmoke_om_docker_stream/project/runServer/yolov5/weights/fireandsmoke_bs1_cann6.3.RC2.om")
with open("/home/css/project/API/model.yaml") as f:
    cfg = yaml.load(f, Loader=yaml.FullLoader)
#设置标签映射
labelnameDict = {1:"fire",  2: "smoke"}
#设置阈值
conf_thres = 0.65
app = FastAPI()
class AreaMonitor(BaseModel):
    area_id: Any = None
    area: List[List[Any]] =None
class Req(BaseModel):
    timestamp: Any = None
    seqid: Any = None
    image: Any = None
    area_monitor: List[AreaMonitor] = None
    image_url: Any = None
app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["POST"],
    allow_headers=["*"],
)

@app.post("/APIService/fireandsmokedetectionService")
async def fireandsmokedetectionService(req:Req):
    #oldold_time = time.time()
    dic_xml = {}
    dic_xml['data'] = []
    dic_xml["seqid"] = ""
    statusCode_str, imgdata,inp_dict,statusMessage_str = getAndCheckInputImageData(req)
    if "seqid" in inp_dict.keys() and inp_dict["seqid"] is not None:
        dic_xml["seqid"] = inp_dict["seqid"]
    #logger.info("获取请求时间:" +str(time.time()-t1))
    if (statusCode_str != '10000'):
        dic_xml['code'] = statusCode_str
        dic_xml['message'] = statusMessage_str

        json_str = json.dumps(dic_xml, ensure_ascii=False)
        del(dic_xml)

        return Response(content=json_str, media_type="application/json;charset=utf-8")
    try:
        #start = time.time()
        #t1 = time.time()
        try:


           showimage = jpeg.decode(imgdata)

        except:
           img_array = np.fromstring(imgdata, np.uint8)  # 转换np序列
           showimage = cv2.imdecode(img_array, cv2.COLOR_BGR2RGB)  # 转换Opencv格式


        dic_xml.update(fireandsmokeDetection_Result_om(showimage, h_model,cfg,conf_thres,labelnameDict))

        dic_xml['code'] = statusCode_str
        #dic_xml['log_id'] = log_id
        dic_xml['message'] = statusMessage_str

        imgH, imgW = showimage.shape[0], showimage.shape[1]
        del showimage
        # 判断是否在监控区域内
        if "area_monitor" in inp_dict.keys() and inp_dict["area_monitor"] is not None:
            #print("在监控区域内")
            monitorResult = []
            for result in dic_xml["data"]:
                part_list = []
                flag = 0
                #print(inp_dict["area_monitor"])
                for monitorArea in inp_dict["area_monitor"]:
                    # ROI区域
                    ROI = np.zeros((imgH, imgW))
                    monitorPoint = monitorArea["area"]

                    ####
                    ROI = point2area_beta(monitorPoint, ROI)
                    obj = [int(result['bbox'][0]),
                           int(result['bbox'][1]),
                           int(result['bbox'][0] + result['bbox'][2]),
                           int(result['bbox'][1] + result['bbox'][3])]
                    #print(obj)
                    if check_objs_roi(obj, ROI):
                        if 'area_id' in monitorArea.keys():
                            monitorID = monitorArea['area_id']
                            #part_list.append(monitorID)
                            result['area_id'] = monitorID
                        if flag == 0:
                            monitorResult.append(result)
                            flag = 1
                            # break
            dic_xml["data"] = monitorResult



        return_str = json.dumps(dic_xml, ensure_ascii=False)
        del(dic_xml)
    except Exception:
        traceback.print_exc()
        dic_xml['code'] = '10903'
        dic_xml['message'] = '服务执行失败'
        #dic_xml['log_id'] = log_id
        json_str = json.dumps(dic_xml,ensure_ascii=False)
        del (dic_xml)
        return Response(content=json_str, media_type="application/json;charset=utf-8")
    newnew_time = time.time()


    return Response(content=return_str, media_type="application/json;charset=utf-8")

运行脚本

#!/bin/bash
source /usr/local/Ascend/ascend-toolkit/set_env.sh
export PYTHONPATH="/home/css/project:$PYTHONPATH"
export rootSaveFile=/data
if [ $max_task_num ]; then
    max_task_num=$max_task_num
else
    max_task_num=14
fi

cd /home/css/project

#### nginx ####
for i in `seq $max_task_num`; do
    port=$((6000+i))
    sed -i "/upstream detection{/a server localhost:$echo$port;" /home/css/nginx/conf/nginx_home.conf
    nohup uvicorn API.imageAPIServerForExample:app --host 0.0.0.0 --port $port &>/dev/null &
done
mkdir -p /usr/share/nginx/logs && mkdir -p /var/log/nginx && mkdir -p /var/lib/nginx/body
chown root:root /usr/sbin/nginx && chmod 777 /usr/sbin/nginx
/usr/sbin/nginx -c /home/css/nginx/conf/nginx_home.conf
netstat -ntulp | grep 5123
cd /home/css/project
python deleteImages.py
/bin/bash
脚本中挂了nginx代理并开了多进程,nginx日志和python日志全关了

使用模型:yolov5-3.1的yolov5m模型结构训练的模型,以batch_size为1转换成了om模型,放入镜像推理

基础镜像使用的是

cke_33720.png

打包镜像后的容器启动命令为

docker run -d -e max_task_num=15 \ 

--device=/dev/davinci0 \ 

--device=/dev/davinci_manager \ 

--device=/dev/devmm_svm \ 

--device=/dev/hisi_hdc \ 

--user root -p 8001:5002 \ 

hx_fireandsmoke_om_bs1:v1.0

容器启动后用docker stats观测容器内存,并且jmeter长时间压测,发现内存缓慢上涨
cke_61507.png
测试团队测试的结果是

cke_75534.png

cke_76788.png


使用的晟腾推理接口是:

from ais_bench.infer.interface import InferSession
model = InferSession(0, "/home/css/project/runServer/yolov5/weights/fireandsmoke_bs1_cann6.3.RC2.om")
result = model.infer([img])

自己写的推理函数是上文的def detect_om(model, img, cfg):

我们的图片流代码在原先的英伟达的A10上也有测试,这次除了推理代码、加载模型的代码、基础镜像进行了改动,其余几乎没有变化,原来的镜像测试内存一直都很稳定,希望华为的老师能协助排查一下,在将推理代码注释掉之后发现内存没有了上涨现象

本帖最后由 匿名用户2024/03/20 08:55:36 编辑

我要发帖子