
çãã®ã¯æåã ãïŒ
ããã«ã¡ã¯ãã¿ããªïŒèŠªæãªãçããããã®èšäºã§ã¯ããªããžããªã«åºã¥ã㊠TensorRTãRetinaNet ã䜿çšããç§ã®çµéšãå
±æããããšæããŸãã (ããã¯å
¬åŒã®ã«ãã®ãã©ãŒã¯ã§ã ããã«ãããæé©åãããã¢ãã«ãå®çšŒåç°å¢ã§ã§ããã ãæ©ã䜿çšãå§ããããšãã§ããŸã)ãã³ãã¥ããã£ãã£ã³ãã«ã®ã¡ãã»ãŒãžãã¹ã¯ããŒã«ãã ãTensorRT ã®äœ¿çšã«é¢ãã質åã«ééããŠããããã®è³ªåã¯ã»ãšãã©ç¹°ãè¿ãããŠãããããæžãããšã«ããŸããã å¯èœãªéãå®å
šãª TensorRTãRetinaNetãUnetãdocker ã«åºã¥ãé«éæšè«ã䜿çšããããã®ã¬ã€ãã
ã¿ã¹ã¯ã®èª¬æ
ã¿ã¹ã¯ã次ã®ããã«å®åŒåããããšãææ¡ããŸããããŒã¿ã»ããã«ã©ãã«ãä»ããPytorch 1.3+ ã§ RetinaNet/Unet ãããã¯ãŒã¯ããã¬ãŒãã³ã°ããååŸããéã¿ã ONNX ã«å€æããæ¬¡ã«ãããã TensorRT ãšã³ãžã³ã«å€æããŠãã§ããã° Docker ã§å šäœãå®è¡ããå¿ èŠããããŸãã Ubuntu 18 ARM (Jetson)* ã¢ãŒããã¯ãã£ã§ã¯éåžžã«æãŸãããç°å¢ã®æåå±éãæå°éã«æããŸããæçµçãªææã¯ãRetinaNet/Unet ã®ãšã¯ã¹ããŒããšãã¬ãŒãã³ã°ã ãã§ãªããå¿ èŠãªãã¹ãŠã®ããŒããŠã§ã¢ãåãããåé¡ããã³ã»ã°ã¡ã³ããŒã·ã§ã³ã·ã¹ãã ã®æ¬æ Œçãªéçºãšãã¬ãŒãã³ã°ã«ã察å¿ã§ããã³ã³ããã«ãªããŸãã
ã¹ããŒãž 1. ç°å¢ã®æºå
ããã§æ³šæããªããã°ãªããªãã®ã¯ãæè¿ç§ã¯ãã¹ã¯ããã ãã·ã³ã devbox äžã§å°ãªããšãäžéšã®ã©ã€ãã©ãªã®äœ¿çšãšå±éãå®å šã«æŸæ£ãããšããããšã§ããäœæããŠã€ã³ã¹ããŒã«ããå¿ èŠãããã®ã¯ãdeb ããã® Python ä»®æ³ç°å¢ãš cuda 10.2 (nvidia ãã©ã€ããŒã XNUMX ã€ã«å¶éã§ããŸã) ã ãã§ãã
æ°ããã€ã³ã¹ããŒã«ãããšä»®å®ããŸããã Ubuntu 18. CUDA 10.2 (deb) ãã€ã³ã¹ããŒã«ããŸããããã€ã³ã¹ããŒã«æé ã«ã€ããŠã¯ãå ¬åŒããã¥ã¡ã³ãã§åå説æãããŠããã®ã§ãããã§ã¯è©³ãã説æããŸããã
ããã§ã¯ãdocker ãã€ã³ã¹ããŒã«ããŸããããdocker ã€ã³ã¹ããŒã« ã¬ã€ãã¯ç°¡åã«èŠã€ãããŸããããã«äŸã瀺ããŸãã ãããŒãžã§ã³ 19 以éã¯ãã§ã«å©çšå¯èœã§ã - ã€ã³ã¹ããŒã«ããŠãã ããããŸããsudo ãªãã§ docker ã䜿çšã§ããããã«ããããšãå¿ããªãã§ãã ãããããããããšã§ãã䟿å©ã«ãªããŸãããã¹ãŠãããŸããã£ãåŸã次ã®ããšãè¡ããŸãã
distribution=$(. /etc/os-release;echo $ID$VERSION_ID)
curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | sudo apt-key add -
curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.list | sudo tee /etc/apt/sources.list.d/nvidia-docker.list
sudo apt-get update && sudo apt-get install -y nvidia-container-toolkit
sudo systemctl restart docker
å ¬åŒãªããžããªãèŠãå¿ èŠãããããŸãã .
ããã§ã¯ git clone ãå®è¡ããŸããã .
æ®ããããã§ããnvidia ã€ã¡ãŒãžã§ docker ã䜿çšãå§ããã«ã¯ãNGC Cloud ã«ç»é²ããŠãã°ã€ã³ããå¿ èŠããããŸããããã«è¡ããŸããã ãç»é²ããNGC Cloud ã«å ¥ã£ãããç»é¢ã®å·Šäžé ã«ãã [ã»ããã¢ãã] ãã¯ãªãã¯ãããããã®ãªã³ã¯ãã¯ãªãã¯ããŸãã ã ãããŒã®çæããã¯ãªãã¯ããŸããä¿åããããšããå§ãããŸããä¿åããªããšã次åã¢ã¯ã»ã¹ãããšãã«å床çæããæ°ããè»ã«å±éããŠãã®æäœãç¹°ãè¿ãå¿ èŠããããŸãã
ãããïŒ
docker login nvcr.io
Username: $oauthtoken
Password: <Your Key> - ÑгеМеÑОÑПваММÑй клÑÑ
ãŠãŒã¶ãŒåã¯åçŽã«ã³ããŒãããŸããããŠããããã€ãããç°å¢ãæ€èšããŠãã ããã
ã¹ããŒãž 2: Docker ã³ã³ããã®æ§ç¯
äœæ¥ã®ç¬¬ 2 段éã§ã¯ãdocker ãæ§ç¯ãããã®å
éšãçè§£ããŸãã
retina-examples ãããžã§ã¯ãã«é¢é£ããã«ãŒã ãã©ã«ããŒã«ç§»åããŠå®è¡ããŸãããã
docker build --build-arg USER=$USER --build-arg UID=$UID --build-arg GID=$GID --build-arg PW=alex -t retinanet:latest retinanet/
çŸåšã®ãŠãŒã¶ãŒã Docker ã«æž¡ãããšã«ãã£ãŠ Docker ãæ§ç¯ããŸããããã¯ãçŸåšã®ãŠãŒã¶ãŒã®æš©éã§ããŠã³ãããã VOLUME ã«äœããæžã蟌ãå Žåã«éåžžã«äŸ¿å©ã§ããããã§ãªãå Žåã¯ãroot ã«ãªãé¢åã«ãªããŸãã
docker ã®æ§ç¯äžã«ãDockerfile ã調ã¹ãŠã¿ãŸãããã
FROM nvcr.io/nvidia/pytorch:19.10-py3
ARG USER=alex
ARG UID=1000
ARG GID=1000
ARG PW=alex
RUN useradd -m ${USER} --uid=${UID} && echo "${USER}:${PW}" | chpasswd
RUN apt-get -y update && apt-get -y upgrade && apt-get -y install curl && apt-get -y install wget && apt-get -y install git && apt-get -y install automake && apt-get install -y sudo && adduser ${USER} sudo
RUN pip install git+https://github.com/bonlime/pytorch-tools.git@master
COPY . retinanet/
RUN pip install --no-cache-dir -e retinanet/
RUN pip install /workspace/retinanet/extras/tensorrt-6.0.1.5-cp36-none-linux_x86_64.whl
RUN pip install tensorboardx
RUN pip install albumentations
RUN pip install setproctitle
RUN pip install paramiko
RUN pip install flask
RUN pip install mem_top
RUN pip install arrow
RUN pip install pycuda
RUN pip install torchvision
RUN pip install pretrainedmodels
RUN pip install efficientnet-pytorch
RUN pip install git+https://github.com/qubvel/segmentation_models.pytorch
RUN pip install pytorch_toolbelt
RUN chown -R ${USER}:${USER} retinanet/
RUN cd /workspace/retinanet/extras/cppapi && mkdir build && cd build && cmake -DCMAKE_CUDA_FLAGS="--expt-extended-lambda -std=c++14" .. && make && cd /workspace
RUN apt-get install -y openssh-server && apt install -y tmux && apt-get -y install bison flex && apt-cache search pcre && apt-get -y install net-tools && apt-get -y install nmap
RUN apt-get -y install libpcre3 libpcre3-dev && apt-get -y install iputils-ping
RUN mkdir /var/run/sshd
RUN echo 'root:pass' | chpasswd
RUN sed -i 's/PermitRootLogin prohibit-password/PermitRootLogin yes/' /etc/ssh/sshd_config
RUN sed 's@sessions*requireds*pam_loginuid.so@session optional pam_loginuid.so@g' -i /etc/pam.d/sshd
ENV NOTVISIBLE "in users profile"
RUN echo "export VISIBLE=now" >> /etc/profile
CMD ["/usr/sbin/sshd", "-D"]
æ¬æããåããããã«ãç§ãã¡ã¯ãæ°ã«å ¥ãã®ã©ã€ãã©ãªããã¹ãŠäœ¿çšããretinanet ãã³ã³ãã€ã«ããäœæ¥ã容æã«ããããã®åºæ¬çãªããŒã«ãããã€ã远å ããŸããã Ubuntu ãããŠãOpenSSHãµãŒããŒãèšå®ããŸããæåã®è¡ã¯ãNGC Cloudãã°ã€ã³ãäœæããNVIDIAã€ã¡ãŒãžãç¶æ¿ããŠããããã®ã€ã¡ãŒãžã«ã¯Pytorch1.3ãTensorRT6.xxxãããã³æ€åºåšã®CPPãœãŒã¹ã³ãŒããã³ã³ãã€ã«ããããã«å¿ èŠãªãã®ä»ã®ã©ã€ãã©ãªã倿°å«ãŸããŠããŸãã
ã¹ããŒãž 3: Docker ã³ã³ããã®èµ·åãšãããã°
ã³ã³ãããŒãšéçºç°å¢ã䜿çšããäž»ãªã±ãŒã¹ã«ç§»ããŸãããããŸããnvidia docker ãèµ·åããŸãããããããïŒ
docker run --gpus all --net=host -v /home/<your_user_name>:/workspace/mounted_vol -d -P --rm --ipc=host -it retinanet:latestã³ã³ããã« ssh çµç±ã§ã¢ã¯ã»ã¹ã§ããããã«ãªããŸãã@ããŒã«ã«ãã¹ããèµ·åã«æåããããPyCharm ã§ãããžã§ã¯ããéããŸããæ¬¡ã«éããŸã
Settings->Project Interpreter->Add->Ssh Interpreter ã¹ããã1

ã¹ããã2

ã¹ããã3

ã¹ã¯ãªãŒã³ã·ã§ããã®ããã«ãã¹ãŠãéžæããŸãã
Interpreter -> /opt/conda/bin/python- ãã㯠Python3.6 ã§ã¯ ln ã«ãªããŸãã
Sync folder -> /workspace/retinanetçµäºãæŒããŠã€ã³ããã¯ã¹äœæãåŸ ã€ã ãã§ãç°å¢ã䜿çšã§ããããã«ãªããŸãã
éèŠïŒ ã€ã³ããã¯ã¹äœæã®çŽåŸã«ãRetinanet çšã«ã³ã³ãã€ã«ããããã¡ã€ã«ã Docker ãããã«ããŸãããããžã§ã¯ã ã«ãŒãã®ã³ã³ããã¹ã ã¡ãã¥ãŒã§ãé ç®ãéžæããŸã
Deployment->Download1 ã€ã®ãã¡ã€ã«ãš 2 ã€ã®ãã©ã«ã㌠(buildãretinanet.egg-infoãããã³ _С.so) ã衚瀺ãããŸãã

ãããžã§ã¯ããæ¬¡ã®ããã§ããã°ãç°å¢ã¯å¿
èŠãªãã¡ã€ã«ããã¹ãŠèªèããŠãããRetinaNet ããã¬ãŒãã³ã°ããæºåãæŽã£ãŠããŸãã
ã¹ããŒãž 4. ããŒã¿ã«ã©ãã«ãä»ããæ€åºåšããã¬ãŒãã³ã°ãã
ç§ãäž»ã«äœ¿çšããããŒã¯ã¢ããã«ã¯ â å¿«é©ã§äŸ¿å©ãªããŒã«ã§ãããæè¿å€ãã®ãã°ãä¿®æ£ãããåäœãå€§å¹ ã«æ¹åãããŸããã
ããŒã¿ã»ãããããŒã¯ã¢ããããŠããŠã³ããŒããããšä»®å®ããŸãããããŒã¿ã»ããã¯ç¬èªã®åœ¢åŒã§ããããã®ããã«ã¯ COCO ã«å€æããå¿ èŠããããããããã« RetinaNet ã«å ¥ããããšã¯ã§ããŸããã倿ããŒã«ã¯æ¬¡ã®å Žæã«ãããŸãã
markup_utils/supervisly_to_coco.pyã¹ã¯ãªããå ã®ã«ããŽãªã¯äžäŸã§ãããç¬èªã®ã«ããŽãªãæ¿å ¥ããå¿ èŠãããããšã«æ³šæããŠãã ãã (èæ¯ã®ã«ããŽãªã远å ããå¿ èŠã¯ãããŸãã)ã
categories = [{'id': 1, 'name': '1'},
{'id': 2, 'name': '2'},
{'id': 3, 'name': '3'},
{'id': 4, 'name': '4'}] äœããã®çç±ã§ãå ã®ãªããžããªã®äœæè ã¯ãæ€åºã®ããã« COCO/VOC 以å€ã®ãã®ã¯ãã¬ãŒãã³ã°ããªããšæ±ºå®ããããããœãŒã¹ ãã¡ã€ã«ãå°ãç·šéããå¿ èŠããããŸããã
retinanet/dataset.pyããã«ãæ°ã«å ¥ãã®æ¡åŒµæ©èœã远å ãããšã ãããŠãCOCO ããåºå®çãªã«ããŽãªãŒãåé€ããŸãã倧ããªæ€åºãšãªã¢ãããªãã³ã°ããããšãã§ããŸãã倧ããªåçã®äžã§å°ããªãªããžã§ã¯ããæ¢ããŠããå ŽåãããŒã¿ã»ãããå°ãã =) ãšäœãæ©èœããŸããããããã«ã€ããŠã¯ãŸãå¥ã®æ©äŒã«èª¬æããŸãã
äžè¬ã«ãé»è»ã®ã«ãŒãã匱ããæåã¯ãã§ãã¯ãã€ã³ããä¿åããªãã£ãããããçš®ã®ã²ã©ãã¹ã±ãžã¥ãŒã©ãŒã䜿çšãããããŠããŸããããã ããããšã¯ããã¯ããŒã³ãéžæããŠå®è¡ããã ãã§ãã
/opt/conda/bin/python retinanet/main.pyãã©ã¡ãŒã¿ä»ã:
train retinanet_rn34fpn.pth
--backbone ResNet34FPN
--classes 12
--val-iters 10
--images /workspace/mounted_vol/dataset/train/images
--annotations /workspace/mounted_vol/dataset/train_12_class.json
--val-images /workspace/mounted_vol/dataset/test/images_small
--val-annotations /workspace/mounted_vol/dataset/val_10_class_cropped.json
--jitter 256 512
--max-size 512
--batch 32
ã³ã³ãœãŒã«ã«ã¯æ¬¡ã®å 容ã衚瀺ãããŸãã
Initializing model...
model: RetinaNet
backbone: ResNet18FPN
classes: 2, anchors: 9
Selected optimization level O0: Pure FP32 training.
Defaults for this optimization level are:
enabled : True
opt_level : O0
cast_model_type : torch.float32
patch_torch_functions : False
keep_batchnorm_fp32 : None
master_weights : False
loss_scale : 1.0
Processing user overrides (additional kwargs that are not None)...
After processing overrides, optimization options are:
enabled : True
opt_level : O0
cast_model_type : torch.float32
patch_torch_functions : False
keep_batchnorm_fp32 : None
master_weights : False
loss_scale : 128.0
Preparing dataset...
loader: pytorch
resize: [1024, 1280], max: 1280
device: 4 gpus
batch: 4, precision: mixed
Training model for 20000 iterations...
[ 1/20000] focal loss: 0.95619, box loss: 0.51584, 4.042s/4-batch (fw: 0.698s, bw: 0.459s), 1.0 im/s, lr: 0.0001
[ 12/20000] focal loss: 0.76191, box loss: 0.31794, 0.187s/4-batch (fw: 0.055s, bw: 0.133s), 21.4 im/s, lr: 0.0001
[ 24/20000] focal loss: 0.65036, box loss: 0.30269, 0.173s/4-batch (fw: 0.045s, bw: 0.128s), 23.1 im/s, lr: 0.0001
[ 36/20000] focal loss: 0.46425, box loss: 0.23141, 0.178s/4-batch (fw: 0.047s, bw: 0.131s), 22.4 im/s, lr: 0.0001
[ 48/20000] focal loss: 0.45115, box loss: 0.23505, 0.180s/4-batch (fw: 0.047s, bw: 0.133s), 22.2 im/s, lr: 0.0001
[ 59/20000] focal loss: 0.38958, box loss: 0.25373, 0.184s/4-batch (fw: 0.049s, bw: 0.134s), 21.8 im/s, lr: 0.0001
[ 71/20000] focal loss: 0.37733, box loss: 0.23988, 0.174s/4-batch (fw: 0.049s, bw: 0.125s), 22.9 im/s, lr: 0.0001
[ 83/20000] focal loss: 0.39514, box loss: 0.23878, 0.181s/4-batch (fw: 0.048s, bw: 0.133s), 22.1 im/s, lr: 0.0001
[ 94/20000] focal loss: 0.39947, box loss: 0.23817, 0.185s/4-batch (fw: 0.050s, bw: 0.134s), 21.6 im/s, lr: 0.0001
[ 105/20000] focal loss: 0.37343, box loss: 0.20238, 0.182s/4-batch (fw: 0.048s, bw: 0.134s), 22.0 im/s, lr: 0.0001
[ 116/20000] focal loss: 0.19689, box loss: 0.17371, 0.183s/4-batch (fw: 0.050s, bw: 0.132s), 21.8 im/s, lr: 0.0001
[ 128/20000] focal loss: 0.20368, box loss: 0.16538, 0.178s/4-batch (fw: 0.046s, bw: 0.131s), 22.5 im/s, lr: 0.0001
[ 140/20000] focal loss: 0.22763, box loss: 0.15772, 0.176s/4-batch (fw: 0.050s, bw: 0.126s), 22.7 im/s, lr: 0.0001
[ 148/20000] focal loss: 0.21997, box loss: 0.18400, 0.585s/4-batch (fw: 0.047s, bw: 0.144s), 6.8 im/s, lr: 0.0001
Average Precision (AP) @[ IoU=0.50:0.95 | area= all | maxDets=100 ] = 0.52674
Average Precision (AP) @[ IoU=0.50 | area= all | maxDets=100 ] = 0.91450
Average Precision (AP) @[ IoU=0.75 | area= all | maxDets=100 ] = 0.35172
Average Precision (AP) @[ IoU=0.50:0.95 | area= small | maxDets=100 ] = 0.61881
Average Precision (AP) @[ IoU=0.50:0.95 | area=medium | maxDets=100 ] = -1.00000
Average Precision (AP) @[ IoU=0.50:0.95 | area= large | maxDets=100 ] = -1.00000
Average Recall (AR) @[ IoU=0.50:0.95 | area= all | maxDets= 1 ] = 0.58824
Average Recall (AR) @[ IoU=0.50:0.95 | area= all | maxDets= 10 ] = 0.61765
Average Recall (AR) @[ IoU=0.50:0.95 | area= all | maxDets=100 ] = 0.61765
Average Recall (AR) @[ IoU=0.50:0.95 | area= small | maxDets=100 ] = 0.61765
Average Recall (AR) @[ IoU=0.50:0.95 | area=medium | maxDets=100 ] = -1.00000
Average Recall (AR) @[ IoU=0.50:0.95 | area= large | maxDets=100 ] = -1.00000
Saving model: 148ãã©ã¡ãŒã¿ã®ã»ããå šäœã調ã¹ãã«ã¯ã次ãåç §ããŠãã ããã
retinanet/main.pyäžè¬ã«ããããã¯æ€åºã®æšæºã§ããã説æãä»ããŠããŸãããã¬ãŒãã³ã°ãéå§ããŠçµæãåŸ ã¡ãŸããæšè«ã®äŸã¯æ¬¡ã®ãšããã§ãã
retinanet/infer_example.pyãŸãã¯æ¬¡ã®ã³ãã³ããå®è¡ããŸãã
/opt/conda/bin/python retinanet/main.py infer retinanet_rn34fpn.pth
--images /workspace/mounted_vol/dataset/test/images
--annotations /workspace/mounted_vol/dataset/val.json
--output result.json
--resize 256
--max-size 512
--batch 32
ãªããžããªã«ã¯ãã§ã« Focal Loss ãšããã€ãã®ããã¯ããŒã³ãçµã¿èŸŒãŸããŠãããç¬èªã®ããã¯ããŒã³ãçµã¿èŸŒãããšãç°¡åã§ã
retinanet/backbones/*.pyèè ãã¯è¡šã®äžã§ããã€ãã®ç¹åŸŽã瀺ããŠããŸãã

torchvision ããååŸããããã¯ããŒã³ ResNeXt50_32x4dFPN ããã³ ResNeXt101_32x8dFPN ããããŸãã
æ€åºã«ã€ããŠå°ãã¯çè§£ã§ãããšæããŸãããå
¬åŒããã¥ã¡ã³ããå¿
ãèªãã§ãã ããã ãšã¯ã¹ããŒãã¢ãŒããšãã®ã³ã°ã¢ãŒããçè§£ãã.
ã¹ããŒãž 5. Resnet ãšã³ã³ãŒããŒã䜿çšãã Unet ã¢ãã«ã®ãšã¯ã¹ããŒããšæšè«
ãæ°ã¥ãããšæããŸãããã»ã°ã¡ã³ããŒã·ã§ã³çšã®ã©ã€ãã©ãªã¯ Dockerfile ã«ã€ã³ã¹ããŒã«ãããŠãããç¹ã«çŽ æŽããã lib ã Unitet ããã±ãŒãžã«ã¯ãæšè«ã®äŸãš pytorch ãã§ãã¯ãã€ã³ãã® TensorRT ãšã³ãžã³ãžã®ãšã¯ã¹ããŒãã®äŸããããŸãã
Unet ã®ãããªã¢ãã«ã ONNX ãã TensoRT ã«ãšã¯ã¹ããŒããããšãã®äž»ãªåé¡ã¯ãåºå®ã®ã¢ãããµã³ãã« ãµã€ãºãèšå®ããããConvTranspose2D ã䜿çšããå¿ èŠãããããšã§ãã
import torch.onnx.symbolic_opset9 as onnx_symbolic
def upsample_nearest2d(g, input, output_size):
# Currently, TRT 5.1/6.0 ONNX Parser does not support all ONNX ops
# needed to support dynamic upsampling ONNX forumlation
# Here we hardcode scale=2 as a temporary workaround
scales = g.op("Constant", value_t=torch.tensor([1., 1., 2., 2.]))
return g.op("Upsample", input, scales, mode_s="nearest")
onnx_symbolic.upsample_nearest2d = upsample_nearest2d
ãã®å€æã䜿çšãããšãONNX ã«ãšã¯ã¹ããŒããããšãã«ãããèªåçã«è¡ãããšãã§ããŸãããTensorRT ã®ããŒãžã§ã³ 7 ã§ã¯ãã§ã«ãã®åé¡ã¯è§£æ±ºãããŠãããããªãåŸ ããªããã°ãªããŸããã
ãŸãšã
docker ã䜿ãå§ãããšããèªåã®ã¿ã¹ã¯ã«å¯Ÿãã docker ã®ããã©ãŒãã³ã¹ã«çåãæããŠããŸãããçŸåšãç§ã®ãŠãããã® 1 ã€ã§ã¯ãè€æ°ã®ã«ã¡ã©ã«ãã£ãŠå€§éã®ãããã¯ãŒã¯ ãã©ãã£ãã¯ãçæãããŠããŸãã

ã€ã³ã¿ãŒãããäžã®ããŸããŸãªãã¹ãã§ã¯ããããã¯ãŒã¯ ã€ã³ã¿ã©ã¯ã·ã§ã³ãš VOLUME ã§ã®èšé²ã«æ¯èŒç倧ããªãªãŒããŒãããããããæªç¥ã®æããã GIL ãååšããããšãå ±åãããŠããŸãããŸãããã¬ãŒã ã®ãã£ããã£ããã©ã€ããŒã®æäœãããã³ãããã¯ãŒã¯çµç±ã§ã®ãã¬ãŒã ã®éä¿¡ã¯ããã®ã¢ãŒãã§ã¯ã¢ãããã¯ãªæäœã§ããããã ããŒããªã¢ã«ã¿ã€ã , ãããã¯ãŒã¯ã®é
å»¶ã¯ç§ã«ãšã£ãŠéåžžã«éèŠã§ãã
ãããããã¹ãŠãããŸããããŸãã =)
PS æ®ã£ãŠããã®ã¯ãã»ã°ã¡ã³ããŒã·ã§ã³ãšå¶äœçšã«ãæ°ã«å ¥ãã®åè»ã«ãŒãã远å ããããšã ãã§ãã
ããããšã
ã³ãã¥ããã£ã®ãããã§ ããããªãã§ã¯éçºã¯äžå¯èœã§ããã©ããããããšã ã圌ã®è²Žéãªã¢ããã€ã¹ãšéåžžã«é«ãããæèã®ãããã§ãDLããããšãç§ã«å§ããŠãããŸããã
æ¬çªç°å¢ã§ã¯æé©åãããã¢ãã«ã䜿çšããŠãã ããã
ãªãŒãã©ã€æ ªåŒäŒç€Ÿ
åºæïŒ habr.com
