01/02绑定gpu0|03/04绑定gpu1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80
| services: ocrserver01: image: zzz container_name: ocrserver01 ports: - "10001:5001" networks: - apps volumes: - /etc/localtime:/etc/localtime environment: CUDA_VISIBLE_DEVICES: "0" shm_size: 8g command: /bin/bash docker/run.sh stdin_open: true tty: true restart: always
ocrserver02: image: zzz container_name: ocrserver02 ports: - "10002:5001" networks: - apps volumes: - /etc/localtime:/etc/localtime environment: CUDA_VISIBLE_DEVICES: "0" shm_size: 8g command: /bin/bash docker/run.sh stdin_open: true tty: true restart: always
ocrserver03: image: zzz container_name: ocrserver03 ports: - "10003:5001" networks: - apps volumes: - /etc/localtime:/etc/localtime environment: CUDA_VISIBLE_DEVICES: "1" shm_size: 8g command: /bin/bash docker/run.sh stdin_open: true tty: true restart: always
ocrserver04: image: zzz container_name: ocrserver04 ports: - "10004:5001" networks: - apps volumes: - /etc/localtime:/etc/localtime environment: CUDA_VISIBLE_DEVICES: "1" shm_size: 8g command: /bin/bash docker/run.sh stdin_open: true tty: true restart: always
networks: apps: external: true
|

1.1当前配置是否正确
你的目标:
| 容器 |
GPU |
| ocrserver01 |
GPU0 |
| ocrserver02 |
GPU0 |
| ocrserver03 |
GPU1 |
| ocrserver04 |
GPU1 |
当前配置:
1 2 3 4 5
| ocrserver01 -> CUDA_VISIBLE_DEVICES: "0" ocrserver02 -> CUDA_VISIBLE_DEVICES: "0"
ocrserver03 -> CUDA_VISIBLE_DEVICES: "1" ocrserver04 -> CUDA_VISIBLE_DEVICES: "1"
|
这是正确的会形成:
1 2 3 4 5 6 7
| GPU0: ocrserver01 ocrserver02
GPU1: ocrserver03 ocrserver04
|
1.2推荐生产级写法
- NVIDIA_VISIBLE_DEVICES 物理层可见性
- CUDA_VISIBLE_DEVICES 程序运行时可见性
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80
| services: ocrserver01: image: xxx container_name: ocrserver01 runtime: nvidia ports: - "10001:5001" environment: NVIDIA_VISIBLE_DEVICES: "0" CUDA_VISIBLE_DEVICES: "0" shm_size: 8g command: /bin/bash docker/run.sh restart: always stdin_open: true tty: true networks: - apps volumes: - /etc/localtime:/etc/localtime:ro ocrserver02: image: xxx container_name: ocrserver02 runtime: nvidia ports: - "10002:5001" environment: NVIDIA_VISIBLE_DEVICES: "0" CUDA_VISIBLE_DEVICES: "0" shm_size: 8g command: /bin/bash docker/run.sh restart: always stdin_open: true tty: true networks: - apps volumes: - /etc/localtime:/etc/localtime:ro
ocrserver03: image: xxx container_name: ocrserver03 runtime: nvidia ports: - "10003:5001" environment: NVIDIA_VISIBLE_DEVICES: "1" CUDA_VISIBLE_DEVICES: "1" shm_size: 8g command: /bin/bash docker/run.sh restart: always stdin_open: true tty: true networks: - apps volumes: - /etc/localtime:/etc/localtime:ro
ocrserver04: image: xxx container_name: ocrserver04 runtime: nvidia ports: - "10004:5001" environment: NVIDIA_VISIBLE_DEVICES: "1" CUDA_VISIBLE_DEVICES: "1" shm_size: 8g command: /bin/bash docker/run.sh restart: always stdin_open: true tty: true networks: - apps volumes: - /etc/localtime:/etc/localtime:ro
networks: apps: external: true
|
1.3.验证 GPU 是否正确绑定
宿主机
查看:
会看到:
1 2 3 4 5 6 7 8 9
| GPU0: python ocrserver01 ocrserver02
GPU1: python ocrserver03 ocrserver04
|
容器内验证
进入:
1
| docker exec -it ocrserver03 bash
|
执行:
理论上只会看到:
而不是全部 GPU。
生产环境建议
你现在:
是合理的,因为 OCR:
- 通常显存占用不高
- 推理偏 IO/CPU
- GPU utilization 不一定满
所以:1卡多实例,通常比:1卡1实例吞吐更高。
nginx负载
flowchart TB
Nginx/LB
--> OCR01
--> OCR02
--> OCR03
--> OCR04
OCR01 --> GPU0
OCR02 --> GPU0
OCR03 --> GPU1
OCR04 --> GPU1
1.1tengine-lb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| services: tengine: image: axizdkr/tengine:alpine3.19.1 container_name: ngx restart: always ports: - "80:80" volumes: - ./logs:/var/log/nginx - ./nginx.conf:/etc/nginx/nginx.conf networks: - apps
networks: apps: external: true
|
1.2.nginx.conf
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
| user nginx; worker_processes auto;
error_log /var/log/nginx/error.log error; pid /var/run/nginx.pid;
events { worker_connections 102400; use epoll; multi_accept on; }
http { include mime.types; default_type application/octet-stream;
# log log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for" "$upstream_addr" "$upstream_response_time" "$request_time" '; access_log /var/log/nginx/access.log main;
#send/tcp sendfile on; tcp_nopush on; tcp_nodelay on;
# Hide web server information server_tokens off; server_info off; server_tag off;
#client reset_timedout_connection on; client_header_timeout 10s; client_body_timeout 12s; client_max_body_size 256m;
#send send_timeout 15s;
#proxy proxy_connect_timeout 15s; proxy_send_timeout 120s; proxy_read_timeout 120s;
#keepalive keepalive_timeout 35;
#gzip gzip on; gzip_types text/plain application/xml;
# redirect server error pages to the static page error_page 404 /404.html; error_page 500 502 503 504 /50x.html;
# ocr识别服务 upstream ocrserver{ server ocrserver01:5001 weight=100; server ocrserver02:5001 weight=100; server ocrserver03:5001 weight=100; server ocrserver04:5001 weight=100; check interval=3000 rise=2 fall=3 timeout=2000 type=tcp; }
server { listen 80; server_name —;
#charset koi8-r; #access_log logs/host.access.log main;
location ~* /predict { proxy_pass http://ocrserver; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
} } }
|