ResNet18을 Target board(VEK280)에서 실행

KiJungKong·2024년 2월 24일
0
post-thumbnail

준비물

.
├── cifar10
│   ├── build_cifar10_test.sh
│   ├── cifar10_labels.dat
│   ├── cifar10_performance.sh
│   ├── code
│   │   ├── build_app.sh
│   │   ├── build_get_dpu_fps.sh
│   │   └── src
│   │       ├── check_runtime_top5_cifar10.py
│   │       ├── get_dpu_fps.cc
│   │       └── main_int8.cc
│   ├── run_all_cifar10_target.sh
│   ├── v70_train1_resnet18_cifar10.xmodel
│   ├── v70_train2_resnet18_cifar10.xmodel
│   ├── vck190_train1_resnet18_cifar10.xmodel
│   ├── vck190_train2_resnet18_cifar10.xmodel
│   ├── vck5000_train1_resnet18_cifar10.xmodel
│   ├── vck5000_train2_resnet18_cifar10.xmodel
│   ├── vek280_train1_resnet18_cifar10.xmodel
│   ├── vek280_train2_resnet18_cifar10.xmodel
│   ├── zcu102_train1_resnet18_cifar10.xmodel
│   └── zcu102_train2_resnet18_cifar10.xmodel
├── common
│   ├── common.cpp
│   └── common.h
├── imagenet
│   ├── code_resnet50
│   │   ├── build_resnet50.sh
│   │   └── src
│   │       ├── check_runtime_top1_imagenet.py
│   │       ├── config
│   │       │   └── imagenet_config.py
│   │       └── main_resnet50.cc
│   ├── imagenet_performance.sh
│   ├── run_all_imagenet_target.sh
│   ├── v70_resnet18_imagenet.xmodel
│   ├── val_dataset.zip
│   ├── vck190_resnet18_imagenet.xmodel
│   ├── vck5000_resnet18_imagenet.xmodel
│   ├── vek280_resnet18_imagenet.xmodel
│   └── zcu102_resnet18_imagenet.xmodel
└── run_all_target.sh

8 directories, 34 files

코드 실행

root@xilinx-vek280-es1-20231:~/target_vek280
> ./run_all_target.sh vek280

target/cifar10/run_all_cifar10_target.sh/main()

main()
{
    clean_cif10
    compile_cif10
    test_images_cif10
    run_cnn_cif10
    end_cif10
}

target/run_all_target.sh

#!/bin/bash

# Copyright © 2023 Advanced Micro Devices, Inc. All rights reserved.
# SPDX-License-Identifier: MIT

# Author: Daniele Bagni, Xilinx Inc
# date:  10 Aug. 2023


source ./cifar10/run_all_cifar10_target.sh   main $1
source ./imagenet/run_all_imagenet_target.sh main $1

target/cifar10/run_all_cifar10_target.sh/clean_cif10()

#clean
clean_cif10(){
echo " "
echo "clean cifar10"
echo " "
cd cifar10
rm -rf test
rm -f *~
rm -f  run_cnn cnn* get_dpu_fps *.txt
rm -rf rpt
rm -f  *.txt
rm -f  *.log
mkdir -p rpt
cd ..
}
clean cifar10

target/cifar10/run_all_cifar10_target.sh/compile_cif10() 앞부분

# compile CNN application
compile_cif10(){
echo " "
echo "compile cifar10"
echo " "
cd cifar10/code
echo "PWD1 = " $PWD
bash -x ./build_app.sh
mv code ../cnn_resnet18_cifar10 # change name of the application
bash -x ./build_get_dpu_fps.sh
mv code ../get_dpu_fps
cd ../..

target/cifar10/code/build_app.sh

#!/bin/sh # 쉘 스크립트의 시작을 알리는 shebang

# 저작권, 라이선스, 저자, 날짜 등의 메타데이터
# Copyright © 2023 Advanced Micro Devices, Inc. All rights reserved.
# SPDX-License-Identifier: MIT

# Author: Daniele Bagni, Xilinx Inc
# date:  28 Apr. 2023


cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 # 현재 스크립트의 디렉토리로 이동
CXX=${CXX:-g++} # CXX 변수가 비어있으면 g++로 설정
os=`lsb_release -a | grep "Distributor ID" | sed 's/^.*:\s*//'` # 운영체제 이름을 os 변수에 저장
os_version=`lsb_release -a | grep "Release" | sed 's/^.*:\s*//'` # 운영체제 버전을 os_version 변수에 저장
arch=`uname -p` # 아키텍처를 arch 변수에 저장
target_info=${os}.${os_version}.${arch} # os, os_version, arch를 합쳐서 target_info 변수에 저장
install_prefix_default=$HOME/.local/${target_info} # 기본 설치 경로를 install_prefix_default 변수에 저장
$CXX --version # CXX로 설정된 컴파일러의 버전을 출력

result=0 && pkg-config --list-all | grep opencv4 && result=1 # opencv4가 설치되어 있는지 확인하고 result 변수에 저장
if [ $result -eq 1 ]; then # result가 1이면 opencv4가 설치되어 있다는 의미
	OPENCV_FLAGS=$(pkg-config --cflags --libs-only-L opencv4) # opencv4의 컴파일 옵션을 OPENCV_FLAGS 변수에 저장
else # result가 1이 아니면 opencv4가 설치되어 있지 않다는 의미
	OPENCV_FLAGS=$(pkg-config --cflags --libs-only-L opencv) # opencv의 컴파일 옵션을 OPENCV_FLAGS 변수에 저장
fi

name=$(basename $PWD) # 현재 디렉토리의 이름을 name 변수에 저장
if [[ "$CXX"  == *"sysroot"* ]];then # CXX 변수에 sysroot라는 문자열이 포함되어 있으면
$CXX -O2 -fno-inline -I. \
     -I=/usr/include/opencv4 \ # opencv4의 헤더 파일 경로를 추가
     -I=/install/Debug/include \ # Debug 모드의 헤더 파일 경로를 추가
     -I=/install/Release/include \ # Release 모드의 헤더 파일 경로를 추가
     -L=/install/Debug/lib \ # Debug 모드의 라이브러리 경로를 추가
     -L=/install/Release/lib \ # Release 모드의 라이브러리 경로를 추가
     -I$PWD/../../common  -o $name -std=c++17 \ # 공통 헤더 파일 경로를 추가하고 출력 파일 이름을 name으로 하고 C++17 표준을 사용
     $PWD/src/main_int8.cc \ # 소스 파일 경로를 지정
     $PWD/../../common/common.cpp  \ # 공통 소스 파일 경로를 지정
     -Wl,-rpath=$PWD/lib \ # 런타임 라이브러리 경로를 지정
     -lvart-runner \ # vart-runner 라이브러리를 링크
     ${OPENCV_FLAGS} \ # opencv 관련 옵션을 적용
     -lopencv_videoio  \ # opencv_videoio 라이브러리를 링크
     -lopencv_imgcodecs \ # opencv_imgcodecs 라이브러리를 링크
     -lopencv_highgui \ # opencv_highgui 라이브러리를 링크
     -lopencv_imgproc \ # opencv_imgproc 라이브러리를 링크
     -lopencv_core \ # opencv_core 라이브러리를 링크
     -lglog \ # glog 라이브러리를 링크
     -lxir \ # xir 라이브러리를 링크
     -lunilog \ # unilog 라이브러리를 링크
     -lpthread # pthread 라이브러리를 링크
else # CXX 변수에 sysroot라는 문자열이 포함되어 있지 않으면
$CXX -O2 -fno-inline -I. \
     -I${install_prefix_default}.Debug/include \ # 기본 설치 경로의 Debug 모드의 헤더 파일 경로를 추가
     -I${install_prefix_default}.Release/include \ # 기본 설치 경로의 Release 모드의 헤더 파일 경로를 추가
     -L${install_prefix_default}.Debug/lib \ # 기본 설치 경로의 Debug 모드의 라이브러리 경로를 추가
     -L${install_prefix_default}.Release/lib \ # 기본 설치 경로의 Release 모드의 라이브러리 경로를 추가
     -Wl,-rpath=${install_prefix_default}.Debug/lib \ # 기본 설치 경로의 Debug 모드의 런타임 라이브러리 경로를 지정
     -Wl,-rpath=${install_prefix_default}.Release/lib \ # 기본 설치 경로의 Release 모드의 런타임 라이브러리 경로를 지정
     -I$PWD/../../common  -o $name -std=c++17 \ # 공통 헤더 파일 경로를 추가하고 출력 파일 이름을 name으로 하고 C++17 표준을 사용
     $PWD/src/main_int8.cc \ # 소스 파일 경로를 지정
     $PWD/../../common/common.cpp  \ # 공통 소스 파일 경로를 지정
     -Wl,-rpath=$PWD/lib \ # 런타임 라이브러리 경로를 지정
     -lvart-runner \ # vart-runner 라이브러리를 링크
     ${OPENCV_FLAGS} \ # opencv 관련 옵션을 적용
     -lopencv_videoio  \ # opencv_videoio 라이브러리를 링크
     -lopencv_imgcodecs \ # opencv_imgcodecs 라이브러리를 링크
     -lopencv_highgui \ # opencv_highgui 라이브러리를 링크
     -lopencv_imgproc \ # opencv_imgproc 라이브러리를 링크
     -lopencv_core \ # opencv_core 라이브러리를 링크
     -lglog \ # glog 라이브러리를 링크
     -lxir \ # xir 라이브러리를 링크
     -lunilog \ # unilog 라이브러리를 링크
     -lpthread # pthread 라이브러리를 링크
fi
	PWD1 =  /home/root/target_vek280/cifar10/code
	++ dirname ./build_app.sh
	+ cd .
	+ CXX=g++
	++ sed 's/^.*:\s*//'
	++ grep 'Distributor ID'
	++ lsb_release -a
	+ os=petalinux
	++ grep Release
	++ sed 's/^.*:\s*//'
	++ lsb_release -a
	+ os_version=2023.1+release-S05010539
	++ uname -p
	+ arch=unknown
	+ target_info=petalinux.2023.1+release-S05010539.unknown
	+ install_prefix_default=/home/root/.local/petalinux.2023.1+release-S05010539.unknown
	+ g++ --version
	g++ (GCC) 12.2.0
	Copyright (C) 2022 Free Software Foundation, Inc.
	This is free software; see the source for copying conditions.  There is NO
	warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
	
	+ result=0
	+ pkg-config --list-all
	+ grep opencv4
	opencv4                             OpenCV - Open Source Computer Vision Library
	+ result=1
	+ '[' 1 -eq 1 ']'
	++ pkg-config --cflags --libs-only-L opencv4
	+ OPENCV_FLAGS=-I/usr/include/opencv4
	++ basename /home/root/target_vek280/cifar10/code
	+ name=code
	+ [[ g++ == *\s\y\s\r\o\o\t* ]]
	+ g++ -O2 -fno-inline -I. -I/home/root/.local/petalinux.2023.1+release-S05010539.unknown.Debug/include -I/home/root/.local/petalinux.2023.1+release-S05010539.unknown.Release/include -L/home/root/.local/petalinux.2023.1+release-S05010539.unknown.Debug/lib -L/home/root/.local/petalinux.2023.1+release-S05010539.unknown.Release/lib -Wl,-rpath=/home/root/.local/petalinux.2023.1+release-S05010539.unknown.Debug/lib -Wl,-rpath=/home/root/.local/petalinux.2023.1+release-S05010539.unknown.Release/lib -I/home/root/target_vek280/cifar10/code/../../common -o code -std=c++17 /home/root/target_vek280/cifar10/code/src/main_int8.cc /home/root/target_vek280/cifar10/code/../../common/common.cpp -Wl,-rpath=/home/root/target_vek280/cifar10/code/lib -lvart-runner -I/usr/include/opencv4 -lopencv_videoio -lopencv_imgcodecs -lopencv_highgui -lopencv_imgproc -lopencv_core -lglog -lxir -lunilog -lpthread

target/cifar10/code/build_get_dpu_fps.sh

#!/bin/bash # 쉘 스크립트의 시작을 알리는 shebang

# 저작권, 라이선스, 저자, 날짜 등의 메타데이터
# Copyright © 2023 Advanced Micro Devices, Inc. All rights reserved.
# SPDX-License-Identifier: MIT

# Author: Daniele Bagni, Xilinx Inc
# date:  28 Apr. 2023

cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 # 현재 스크립트의 디렉토리로 이동
CXX=${CXX:-g++} # CXX 변수가 비어있으면 g++로 설정
os=`lsb_release -a | grep "Distributor ID" | sed 's/^.*:\s*//'` # 운영체제 이름을 os 변수에 저장
os_version=`lsb_release -a | grep "Release" | sed 's/^.*:\s*//'` # 운영체제 버전을 os_version 변수에 저장
arch=`uname -p` # 아키텍처를 arch 변수에 저장
target_info=${os}.${os_version}.${arch} # os, os_version, arch를 합쳐서 target_info 변수에 저장
install_prefix_default=$HOME/.local/${target_info} # 기본 설치 경로를 install_prefix_default 변수에 저장
$CXX --version # CXX로 설정된 컴파일러의 버전을 출력

result=0 && pkg-config --list-all | grep opencv4 && result=1 # opencv4가 설치되어 있는지 확인하고 result 변수에 저장
if [ $result -eq 1 ]; then # result가 1이면 opencv4가 설치되어 있다는 의미
	OPENCV_FLAGS=$(pkg-config --cflags --libs-only-L opencv4) # opencv4의 컴파일 옵션을 OPENCV_FLAGS 변수에 저장
else # result가 1이 아니면 opencv4가 설치되어 있지 않다는 의미
	OPENCV_FLAGS=$(pkg-config --cflags --libs-only-L opencv) # opencv의 컴파일 옵션을 OPENCV_FLAGS 변수에 저장
fi

name=$(basename $PWD) # 현재 디렉토리의 이름을 name 변수에 저장
if [[ "$CXX"  == *"sysroot"* ]];then # CXX 변수에 sysroot라는 문자열이 포함되어 있으면
$CXX -O2 -fno-inline -I. \
     -I=/usr/include/opencv4 \ # opencv4의 헤더 파일 경로를 추가
     -I=/install/Debug/include \ # Debug 모드의 헤더 파일 경로를 추가
     -I=/install/Release/include \ # Release 모드의 헤더 파일 경로를 추가
     -L=/install/Debug/lib \ # Debug 모드의 라이브러리 경로를 추가
     -L=/install/Release/lib \ # Release 모드의 라이브러리 경로를 추가
     -I$PWD/../../common  -o $name -std=c++17 \ # 공통 헤더 파일 경로를 추가하고 출력 파일 이름을 name으로 하고 C++17 표준을 사용
     $PWD/src/get_dpu_fps.cc \ # 소스 파일 경로를 지정
     $PWD/../../common/common.cpp  \ # 공통 소스 파일 경로를 지정
     -Wl,-rpath=$PWD/lib \ # 런타임 라이브러리 경로를 지정
     -lvart-runner \ # vart-runner 라이브러리를 링크
     ${OPENCV_FLAGS} \ # opencv 관련 옵션을 적용
     -lopencv_videoio  \ # opencv_videoio 라이브러리를 링크
     -lopencv_imgcodecs \ # opencv_imgcodecs 라이브러리를 링크
     -lopencv_highgui \ # opencv_highgui 라이브러리를 링크
     -lopencv_imgproc \ # opencv_imgproc 라이브러리를 링크
     -lopencv_core \ # opencv_core 라이브러리를 링크
     -lglog \ # glog 라이브러리를 링크
     -lxir \ # xir 라이브러리를 링크
     -lunilog \ # unilog 라이브러리를 링크
     -lpthread # pthread 라이브러리를 링크
else # CXX 변수에 sysroot라는 문자열이 포함되어 있지 않으면
$CXX -O2 -fno-inline -I. \
     -I${install_prefix_default}.Debug/include \ # 기본 설치 경로의 Debug 모드의 헤더 파일 경로를 추가
     -I${install_prefix_default}.Release/include \ # 기본 설치 경로의 Release 모드의 헤더 파일 경로를 추가
     -L${install_prefix_default}.Debug/lib \ # 기본 설치 경로의 Debug 모드의 라이브러리 경로를 추가
     -L${install_prefix_default}.Release/lib \ # 기본 설치 경로의 Release 모드의 라이브러리 경로를 추가
     -Wl,-rpath=${install_prefix_default}.Debug/lib \ # 기본 설치 경로의 Debug 모드의 런타임 라이브러리 경로를 지정
     -Wl,-rpath=${install_prefix_default}.Release/lib \ # 기본 설치 경로의 Release 모드의 런타임 라이브러리 경로를 지정
     -I$PWD/../../common  -o $name -std=c++17 \ # 공통 헤더 파일 경로를 추가하고 출력 파일 이름을 name으로 하고 C++17 표준을 사용
     $PWD/src/get_dpu_fps.cc \ # 소스 파일 경로를 지정
     $PWD/../../common/common.cpp  \ # 공통 소스 파일 경로를 지정
     -Wl,-rpath=$PWD/lib \ # 런타임 라이브러리 경로를 지정
     -lvart-runner \ # vart-runner 라이브러리를 링크
     ${OPENCV_FLAGS} \ # opencv 관련 옵션을 적용
     -lopencv_videoio  \ # opencv_videoio 라이브러리를 링크
     -lopencv_imgcodecs \ # opencv_imgcodecs 라이브러리를 링크
     -lopencv_highgui \ # opencv_highgui 라이브러리를 링크
     -lopencv_imgproc \ # opencv_imgproc 라이브러리를 링크
     -lopencv_core \ # opencv_core 라이브러리를 링크
     -lglog \ # glog 라이브러리를 링크
     -lxir \ # xir 라이브러리를 링크
     -lunilog \ # unilog 라이브러리를 링크
     -lpthread # pthread 라이브러리를 링크
fi
	++ dirname ./build_get_dpu_fps.sh
	+ cd .
	+ CXX=g++
	++ sed 's/^.*:\s*//'
	++ lsb_release -a
	++ grep 'Distributor ID'
	+ os=petalinux
	++ lsb_release -a
	++ sed 's/^.*:\s*//'
	++ grep Release
	+ os_version=2023.1+release-S05010539
	++ uname -p
	+ arch=unknown
	+ target_info=petalinux.2023.1+release-S05010539.unknown
	+ install_prefix_default=/home/root/.local/petalinux.2023.1+release-S05010539.unknown
	+ g++ --version
	g++ (GCC) 12.2.0
	Copyright (C) 2022 Free Software Foundation, Inc.
	This is free software; see the source for copying conditions.  There is NO
	warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
	
	+ result=0
	+ grep opencv4
	+ pkg-config --list-all
	opencv4                             OpenCV - Open Source Computer Vision Library
	+ result=1
	+ '[' 1 -eq 1 ']'
	++ pkg-config --cflags --libs-only-L opencv4
	+ OPENCV_FLAGS=-I/usr/include/opencv4
	++ basename /home/root/target_vek280/cifar10/code
	+ name=code
	+ [[ g++ == *\s\y\s\r\o\o\t* ]]
	+ g++ -O2 -fno-inline -I. -I/home/root/.local/petalinux.2023.1+release-S05010539.unknown.Debug/include -I/home/root/.local/petalinux.2023.1+release-S05010539.unknown.Release/include -L/home/root/.local/petalinux.2023.1+release-S05010539.unknown.Debug/lib -L/home/root/.local/petalinux.2023.1+release-S05010539.unknown.Release/lib -Wl,-rpath=/home/root/.local/petalinux.2023.1+release-S05010539.unknown.Debug/lib -Wl,-rpath=/home/root/.local/petalinux.2023.1+release-S05010539.unknown.Release/lib -I/home/root/target_vek280/cifar10/code/../../common -o code -std=c++17 /home/root/target_vek280/cifar10/code/src/get_dpu_fps.cc /home/root/target_vek280/cifar10/code/../../common/common.cpp -Wl,-rpath=/home/root/target_vek280/cifar10/code/lib -lvart-runner -I/usr/include/opencv4 -lopencv_videoio -lopencv_imgcodecs -lopencv_highgui -lopencv_imgproc -lopencv_core -lglog -lxir -lunilog -lpthread
	/home/root/target_vek280/cifar10/code/src/get_dpu_fps.cc: In function 'void runDPU(vart::Runner*, int8_t*, int8_t*)':
	/home/root/target_vek280/cifar10/code/src/get_dpu_fps.cc:47:45: warning: 'virtual const std::vector<int> xir::Tensor::get_dims() const' is deprecated: Tensor::get_dims() will be removed in the future version. Please use the Tensor::get_shape() instead. [-Wdeprecated-declarations]
	   47 |   auto out_dims = outputTensors[0]->get_dims();
	      |                   ~~~~~~~~~~~~~~~~~~~~~~~~~~^~
	In file included from /usr/include/vart/mm/host_flat_tensor_buffer.hpp:21,
	                 from /home/root/target_vek280/cifar10/code/../../common/common.h:23,
	                 from /home/root/target_vek280/cifar10/code/src/get_dpu_fps.cc:31:
	/usr/include/xir/tensor/tensor.hpp:136:7: note: declared here
	  136 |       get_dims() const = 0;
	      |       ^~~~~~~~
	/home/root/target_vek280/cifar10/code/src/get_dpu_fps.cc:48:43: warning: 'virtual const std::vector<int> xir::Tensor::get_dims() const' is deprecated: Tensor::get_dims() will be removed in the future version. Please use the Tensor::get_shape() instead. [-Wdeprecated-declarations]
	   48 |   auto in_dims = inputTensors[0]->get_dims();
	      |                  ~~~~~~~~~~~~~~~~~~~~~~~~~^~
	/usr/include/xir/tensor/tensor.hpp:136:7: note: declared here
	  136 |       get_dims() const = 0;
	      |       ^~~~~~~~

target/cifar10/run_all_cifar10_target.sh/compile_cif10() 뒷부분

echo "PWD2 = " $PWD
}
	PWD2 =  /home/root/target_vek280

target/cifar10/run_all_cifar10_target.sh/test_images_cif10()

# build cifar10 test images
test_images_cif10(){
echo " "
echo "build test images for cifar10"
echo " "
cd cifar10
bash ./build_cifar10_test.sh
cd ..
echo " "
echo "PWD3 = " $PWD
}
	build test images for cifar10
	
	
	PWD3 =  /home/root/target_vek280

target/cifar10/build_cifar10_test.sh

#!/bin/bash

# Copyright © 2023 Advanced Micro Devices, Inc. All rights reserved.
# SPDX-License-Identifier: MIT

# Author: Daniele Bagni, Xilinx Inc
# date:  28 Apr. 2023


# airplane automobile bird cat deer dog frog horse ship truck

tar -xvf test.tar &> /dev/null
#mv ./build/dataset/cifar10/test ./test
#rm -r ./build
cd ./test

cd automobile
mv *.png ../
cd ..
rm -r automobile/

cd airplane
mv *.png ../
cd ..
rm -r airplane/

cd bird
mv *.png ../
cd ..
rm -r bird/

cd cat
mv *.png ../
cd ..
rm -r cat/

cd deer
mv *.png ../
cd ..
rm -r deer/

cd dog
mv *.png ../
cd ..
rm -r dog/

cd frog
mv *.png ../
cd ..
rm -r frog/

cd horse
mv *.png ../
cd ..
rm -r horse/

cd ship
mv *.png ../
cd ..
rm -r ship

cd truck
mv *.png ../
cd ..
rm -r truck

cd ..

target/cifar10/run_all_cifar10_target.sh/run_cnn_cif10() 앞부분

# now run the cifar10 classification with 4 CNNs using VART C++ APIs
run_cnn_cif10(){
echo " "
echo " run cifar10 CNN"
echo " "
cd cifar10
./cnn_resnet18_cifar10 ./${TARGET}_train1_resnet18_cifar10.xmodel ./test/ ./cifar10_labels.dat | tee ./rpt/predictions_cifar10_resnet18.log
	 run cifar10 CNN
/* // 저작권, 라이선스, 저자, 날짜 등의 메타데이터를 표시하는 주석
 * @brief Entry for running CNN // CNN을 실행하기 위한 진입점을 설명하는 주석
 *
 * @note Runner APIs prefixed with "dpu" are used to easily program &
 *       deploy CNN on DPU platform. // DPU 플랫폼에서 CNN을 쉽게 프로그래밍하고 배포하기 위해 "dpu"로 시작하는 Runner API를 사용한다는 주석
 *
 */

// based on  Vitis AI 3.0 VART "resnet50.cc" demo code // 이 코드가 Vitis AI 3.0 VART의 resnet50.cc 데모 코드를 기반으로 한다는 주석

#include <assert.h> // assert 함수를 사용하기 위한 헤더 파일
#include <dirent.h> // 디렉토리 관련 함수를 사용하기 위한 헤더 파일
#include <stdio.h> // 표준 입출력 함수를 사용하기 위한 헤더 파일
#include <stdlib.h> // 표준 라이브러리 함수를 사용하기 위한 헤더 파일
#include <sys/stat.h> // 파일 상태 관련 함수를 사용하기 위한 헤더 파일
#include <unistd.h> // 유닉스 표준 함수를 사용하기 위한 헤더 파일

#include <cassert> // assert 매크로를 사용하기 위한 헤더 파일
#include <cmath> // 수학 함수를 사용하기 위한 헤더 파일
#include <cstdio> // 표준 입출력 함수를 사용하기 위한 헤더 파일
#include <fstream> // 파일 입출력 스트림을 사용하기 위한 헤더 파일
#include <iomanip> // 입출력 조작자를 사용하기 위한 헤더 파일
#include <iostream> // 표준 입출력 스트림을 사용하기 위한 헤더 파일
#include <queue> // 큐 컨테이너를 사용하기 위한 헤더 파일
#include <string> // 문자열 클래스를 사용하기 위한 헤더 파일
#include <vector> // 벡터 컨테이너를 사용하기 위한 헤더 파일

#include "common.h" // 공통 헤더 파일
/* header file OpenCV for image processing */ // 이미지 처리를 위한 OpenCV 헤더 파일
#include <opencv2/opencv.hpp>

using namespace std; // 표준 네임스페이스를 사용
using namespace cv; // OpenCV 네임스페이스를 사용

GraphInfo shapes; // 그래프 정보를 저장할 구조체 변수 선언

//const string baseImagePath = "./test/";
//const string wordsPath = "./";
string baseImagePath, wordsPath;  // they will get their values via argv[] // 이미지 경로와 레이블 경로를 저장할 문자열 변수 선언, argv[]를 통해 값을 받음

/**
 * @brief put image names to a vector // 이미지 이름을 벡터에 넣는 함수를 설명하는 주석
 *
 * @param path - path of the image direcotry // 이미지 디렉토리의 경로를 인자로 받음
 * @param images - the vector of image name // 이미지 이름을 저장할 벡터를 인자로 받음
 *
 * @return none // 반환값은 없음
 */
void ListImages(string const& path, vector<string>& images) { // 이미지 파일 이름을 벡터에 저장하는 함수를 선언
  images.clear(); // images 벡터를 비움
  struct dirent* entry; // 디렉토리 항목을 가리킬 포인터를 선언

  /*Check if path is a valid directory path. */ // path가 유효한 디렉토리 경로인지 확인하는 주석
  struct stat s; // 파일 상태 정보를 저장할 구조체 변수를 선언
  lstat(path.c_str(), &s); // path에 해당하는 파일의 상태 정보를 s에 저장
  if (!S_ISDIR(s.st_mode)) { // s의 모드가 디렉토리가 아니면
    fprintf(stderr, "Error: %s is not a valid directory!\n", path.c_str()); // 표준 에러 스트림에 에러 메시지를 출력
    exit(1); // 프로그램을 종료
  }

  DIR* dir = opendir(path.c_str()); // path에 해당하는 디렉토리를 열고 그 포인터를 dir에 저장
  if (dir == nullptr) { // dir이 nullptr이면
    fprintf(stderr, "Error: Open %s path failed.\n", path.c_str()); // 표준 에러 스트림에 에러 메시지를 출력
    exit(1); // 프로그램을 종료
  }

  while ((entry = readdir(dir)) != nullptr) { // dir에서 디렉토리 항목을 하나씩 읽어서 entry에 저장하고, nullptr이 아니면 반복
    if (entry->d_type == DT_REG || entry->d_type == DT_UNKNOWN) { // entry의 타입이 일반 파일이거나 알 수 없는 타입이면
      string name = entry->d_name; // entry의 이름을 name에 저장
      string ext = name.substr(name.find_last_of(".") + 1); // name에서 마지막 "." 이후의 부분을 ext에 저장
      if ((ext == "JPEG") || (ext == "jpeg") || (ext == "JPG") || // ext가 JPEG, JPG, PNG의 대소문자 변형 중 하나이면
          (ext == "jpg") || (ext == "PNG") || (ext == "png")) {
        images.push_back(name); // images 벡터에 name을 추가
      }
    }
  }

  closedir(dir); // dir을 닫음
}

/**
 * @brief load kinds from file to a vector // 파일에서 종류를 읽어서 벡터에 저장하는 함수를 설명하는 주석
 *
 * @param path - path of the kinds file // 종류 파일의 경로를 인자로 받음
 * @param kinds - the vector of kinds string // 종류 문자열을 저장할 벡터를 인자로 받음
 *
 * @return none // 반환값은 없음
 */
void LoadWords(string const& path, vector<string>& kinds) { // 종류를 읽어서 벡터에 저장하는 함수를 선언
  kinds.clear(); // kinds 벡터를 비움
  ifstream fkinds(path); // path에 해당하는 파일을 열고 그 입력 파일 스트림을 fkinds에 저장
  if (fkinds.fail()) { // fkinds가 실패하면
    fprintf(stderr, "Error : Open %s failed.\n", path.c_str()); // 표준 에러 스트림에 에러 메시지를 출력
    exit(1); // 프로그램을 종료
  }
  string kind; // 종류를 저장할 문자열 변수를 선언
  while (getline(fkinds, kind)) { // fkinds에서 한 줄씩 읽어서 kind에 저장하고, 성공하면 반복
    kinds.push_back(kind); // kinds 벡터에 kind를 추가
  }

  fkinds.close(); // fkinds를 닫음
}

/**
 * @brief calculate softmax // 소프트맥스 계산하는 함수를 설명하는 주석
 *
 * @param data - pointer to input buffer // 입력 버퍼를 가리키는 포인터를 인자로 받음
 * @param size - size of input buffer // 입력 버퍼의 크기를 인자로 받음
 * @param result - calculation result // 계산 결과를 저장할 포인터를 인자로 받음
 *
 * @return none // 반환값은 없음
 */
void CPUCalcSoftmax(const int8_t* data, size_t size, float* result, float scale) { // 소프트맥스 계산하는 함수를 선언
  assert(data && result); // data와 result가 nullptr이 아닌지 확인
  double sum = 0.0f; // 합계를 저장할 변수를 선언하고 0으로 초기화

  for (size_t i = 0; i < size; i++) { // 입력 버퍼의 크기만큼 반복
    result[i] = exp((float)data[i] * scale); // 입력 값에 스케일을 곱하고 지수 함수를 적용하여 결과에 저장
    sum += result[i]; // 결과 값을 합계에 더함
  }
  for (size_t i = 0; i < size; i++) { // 입력 버퍼의 크기만큼 반복
    result[i] /= sum; // 결과 값을 합계로 나누어 소프트맥스 값을 구함
  }
}

void ArgMax(const int8_t* data,  size_t size, float *res_val, int *res_index, float scale) // 최대값과 그 인덱스를 구하는 함수를 선언
{
  int index = 0; // 인덱스를 저장할 변수를 선언하고 0으로 초기화
  int8_t max = data[0]; // 최대값을 저장할 변수를 선언하고 첫 번째 입력 값으로 초기화
  for (size_t i = 1; i < size; i++) // 입력 버퍼의 크기만큼 반복
  {
      if (data[i] > max) // 입력 값이 최대값보다 크면
      {
        max = data[i]; // 최대값을 입력 값으로 갱신
        index = i; // 인덱스를 현재 위치로 갱신
      }
  }
  *res_val   = (float) (max * scale); // 최대값에 스케일을 곱하여 res_val에 저장
  *res_index = index; // 인덱스를 res_index에 저장
}

/**
 * @brief Get top k results according to its probability // 확률에 따라 상위 k개의 결과를 구하는 함수를 설명하는 주석
 *
 * @param d - pointer to input data // 입력 데이터를 가리키는 포인터를 인자로 받음
 * @param size - size of input data // 입력 데이터의 크기를 인자로 받음
 * @param k - calculation result // 계산 결과를 인자로 받음
 * @param vkinds - vector of kinds // 종류를 저장한 벡터를 인자로 받음
 *
 * @return none // 반환값은 없음
 */
void TopK(const float* d, int size, int k, vector<string>& vkinds) { // 상위 k개의 결과를 구하는 함수를 선언
  assert(d && size > 0 && k > 0); // d와 size, k가 nullptr이 아니고 양수인지 확인
  priority_queue<pair<float, int>> q; // 우선순위 큐를 선언하고, 원소는 float과 int의 쌍으로 구성

  for (auto i = 0; i < size; ++i) { // 입력 데이터의 크기만큼 반복
    q.push(pair<float, int>(d[i], i)); // 입력 데이터의 값과 인덱스를 쌍으로 만들어서 큐에 삽입
  }

  for (auto i = 0; i < k; ++i) { // k번 반복
    pair<float, int> ki = q.top(); // 큐의 맨 앞에 있는 원소를 ki에 저장
    printf("top[%d] prob = %-8f  name = %s\n", i, d[ki.second], // ki의 인덱스에 해당하는 입력 데이터의 값과 종류를 출력
           vkinds[ki.second].c_str());
    q.pop(); // 큐의 맨 앞에 있는 원소를 제거
  }
}

/**
 * @brief Run DPU Task for CNN // CNN 모델을 DPU에서 실행하는 함수를 설명하는 주석
 *
 * @return none // 반환값은 없음
 */
void run_CNN(vart::Runner* runner) { // CNN 모델을 실행하는 함수를 선언

  vector<string> kinds, images; // 종류와 이미지 이름을 저장할 벡터를 선언

  /* Load all image names.*/ // 모든 이미지 이름을 불러오는 주석
  ListImages(baseImagePath, images); // baseImagePath에 해당하는 디렉토리에서 이미지 이름을 images 벡터에 저장하는 함수를 호출
  if (images.size() == 0) { // images 벡터의 크기가 0이면
    cerr << "\nError: No images existing under " << baseImagePath << endl; // 표준 에러 스트림에 에러 메시지를 출력
    return; // 함수를 종료
  }

  /* Load all kinds words.*/ // 모든 종류 단어를 불러오는 주석
  //LoadWords(wordsPath + "labels.txt", kinds); // 이 부분은 주석 처리되어 있음
  LoadWords(wordsPath, kinds); // wordsPath에 해당하는 파일에서 종류 단어를 kinds 벡터에 저장하는 함수를 호출
  if (kinds.size() == 0) { // kinds 벡터의 크기가 0이면
    cerr << "\nError: No words exist in file " << wordsPath << endl; // 표준 에러 스트림에 에러 메시지를 출력
    return; // 함수를 종료
  }
  //float mean[3] = {104, 107, 123}; // 이 부분은 주석 처리되어 있음

  /* get in/out tensors and dims*/ // 입출력 텐서와 차원을 가져오는 주석
  auto outputTensors = runner->get_output_tensors(); // 러너에서 출력 텐서를 가져옴
  auto inputTensors = runner->get_input_tensors(); // 러너에서 입력 텐서를 가져옴
  auto out_dims = outputTensors[0]->get_shape(); //_dims(); // 출력 텐서의 모양을 out_dims에 저장
  auto in_dims = inputTensors[0]->get_shape(); //dims(); // 입력 텐서의 모양을 in_dims에 저장

  auto input_scale = get_input_scale(inputTensors[0]); // 입력 텐서의 스케일을 input_scale에 저장
  auto output_scale = get_output_scale(outputTensors[0]); // 출력 텐서의 스케일을 output_scale에 저장

  /*get shape info*/ // 모양 정보를 가져오는 주석
  int outSize = shapes.outTensorList[0].size; // shapes 구조체의 outTensorList의 첫 번째 원소의 크기를 outSize에 저장
  int inSize = shapes.inTensorList[0].size; // shapes 구조체의 inTensorList의 첫 번째 원소의 크기를 inSize에 저장
  int inHeight = shapes.inTensorList[0].height; // shapes 구조체의 inTensorList의 첫 번째 원소의 높이를 inHeight에 저장
  int inWidth = shapes.inTensorList[0].width; // shapes 구조체의 inTensorList의 첫 번째 원소의 너비를 inWidth에 저장
  int batchSize = in_dims[0]; // in_dims의 첫 번째 원소를 batchSize에 저장

  //for debug // 디버깅을 위한 주석
  cout << "OUT  size " << outSize   << endl; // 표준 출력 스트림에 outSize를 출력
  cout << "IN   size " << inSize    << endl; // 표준 출력 스트림에 inSize를 출력
  cout << "IN Height " << inHeight  << endl; // 표준 출력 스트림에 inHeight를 출력
  cout << "IN Width  " << inWidth   << endl; // 표준 출력 스트림에 inWidth를 출력
  cout << "batchSize " << batchSize << endl; // 표준 출력 스트림에 batchSize를 출력

  std::vector<std::unique_ptr<vart::TensorBuffer>> inputs, outputs; // 입력과 출력 텐서 버퍼를 저장할 벡터를 선언

  vector<Mat> imageList; // 이미지를 저장할 벡터를 선언
  int8_t* imageInputs = new int8_t[inSize * batchSize]; // 이미지 입력을 저장할 동적 배열을 선언

  float* softmax = new float[outSize]; // 소프트맥스 값을 저장할 동적 배열을 선언
  int8_t* FCResult = new int8_t[batchSize * outSize]; // 완전 연결 계층의 결과를 저장할 동적 배열을 선언
  std::vector<vart::TensorBuffer*> inputsPtr, outputsPtr; // 입력과 출력 텐서 버퍼의 포인터를 저장할 벡터를 선언
  std::vector<std::shared_ptr<xir::Tensor>> batchTensors; // 배치 텐서를 저장할 벡터를 선언

  /*run with batch*/ // 배치 단위로 실행하는 주석
  for (unsigned int n = 0; n < images.size(); n += batchSize) { // images 벡터의 크기만큼 배치 사이즈만큼 증가시키면서 반복
    unsigned int runSize = // 실행할 사이즈를 runSize에 저장
        (images.size() < (n + batchSize)) ? (images.size() - n) : batchSize; // images 벡터의 크기가 n + batchSize보다 작으면 images 벡터의 크기에서 n을 빼고, 아니면 배치 사이즈를 사용
    in_dims[0] = runSize; // in_dims의 첫 번째 원소를 runSize로 설정
    out_dims[0] = batchSize; // out_dims의 첫 번째 원소를 batchSize로 설정
    for (unsigned int i = 0; i < runSize; i++) // runSize만큼 반복
    {
      Mat image = imread(baseImagePath + images[n + i]); // baseImagePath와 images 벡터의 n + i 번째 원소를 합친 경로의 이미지를 읽어서 image에 저장

      /*image pre-process*/ // 이미지 전처리하는 주석
      Mat image2 = cv::Mat(inHeight, inWidth, CV_8SC3); // inHeight와 inWidth를 크기로 가지는 8비트 부호 있는 3채널 행렬을 image2에 생성
      resize(image, image2, Size(inHeight, inWidth), 0, 0, INTER_NEAREST); // image를 image2의 크기로 리사이즈하고, 보간법은 최근접 이웃법을 사용
      for (int h = 0; h < inHeight; h++) { // inHeight만큼 반복
        for (int w = 0; w < inWidth; w++) { // inWidth만큼 반복
          for (int c = 0; c < 3; c++) { // 3번 반복
            imageInputs[i*inSize+h*inWidth*3+w*3 +  c] = (int8_t)( (image2.at<Vec3b>(h, w)[c]/255.0f-0.5f)*2*input_scale ); //in BGR mode // image2의 h, w 위치의 c 채널의 값을 255로 나누고 0.5를 빼고 2를 곱하고 input_scale을 곱한 후 int8_t로 변환하여 imageInputs의 해당 위치에 저장
	  //imageInputs[i*inSize+h*inWidth*3+w*3 +2-c] = (int8_t)( (image2.at<Vec3b>(h, w)[c]/255.0f-0.5f)*2*input_scale ); //in RGB mode // 이 부분은 주석 처리되어 있음
          }
        }
      }
      imageList.push_back(image); // imageList 벡터에 image를 추가
    }

/* in/out tensor refactory for batch inout/output */ // 배치 입력/출력을 위한 텐서 재구성
    batchTensors.push_back(std::shared_ptr<xir::Tensor>( // 배치 텐서 벡터에 새로운 텐서 포인터 추가
        xir::Tensor::create(inputTensors[0]->get_name(), in_dims, // 입력 텐서의 이름과 차원으로 텐서 생성
                            xir::DataType{xir::DataType::XINT, 8u}))); // 데이터 타입은 8비트 부호 없는 정수
    inputs.push_back(std::make_unique<CpuFlatTensorBuffer>( // 입력 버퍼 벡터에 새로운 텐서 버퍼 추가
        imageInputs, batchTensors.back().get())); // 이미지 입력 데이터와 배치 텐서를 텐서 버퍼로 만듦
    batchTensors.push_back(std::shared_ptr<xir::Tensor>( // 배치 텐서 벡터에 새로운 텐서 포인터 추가
        xir::Tensor::create(outputTensors[0]->get_name(), out_dims, // 출력 텐서의 이름과 차원으로 텐서 생성
                            xir::DataType{xir::DataType::XINT, 8u}))); // 데이터 타입은 8비트 부호 없는 정수
    outputs.push_back(std::make_unique<CpuFlatTensorBuffer>( // 출력 버퍼 벡터에 새로운 텐서 버퍼 추가
        FCResult, batchTensors.back().get())); // FCResult 데이터와 배치 텐서를 텐서 버퍼로 만듦

    /*tensor buffer input/output */ // 텐서 버퍼 입력/출력
    inputsPtr.clear(); // 입력 포인터 벡터 초기화
    outputsPtr.clear(); // 출력 포인터 벡터 초기화
    inputsPtr.push_back(inputs[0].get()); // 입력 포인터 벡터에 첫 번째 입력 버퍼의 포인터 추가
    outputsPtr.push_back(outputs[0].get()); // 출력 포인터 벡터에 첫 번째 출력 버퍼의 포인터 추가

    /*run*/ // 실행
    auto job_id = runner->execute_async(inputsPtr, outputsPtr); // 비동기 방식으로 DPU 러너에 입력/출력 포인터 전달하고 작업 ID 받음
    runner->wait(job_id.first, -1); // 작업 ID에 해당하는 작업이 완료될 때까지 대기
    for (unsigned int i = 0; i < runSize; i++) { // 실행 크기만큼 반복
      cout << "\nImage : " << images[n + i] << endl; // 이미지 이름 출력
      /* Calculate softmax on CPU and display TOP-5 classification results */ // CPU에서 소프트맥스 계산하고 상위 5개 분류 결과 출력
      CPUCalcSoftmax(&FCResult[i * outSize], outSize, softmax,  output_scale); // FCResult의 i번째 출력에 대해 소프트맥스 계산하고 softmax 배열에 저장
      TopK(softmax, outSize, 5, kinds); // softmax 배열에서 상위 5개의 인덱스와 확률을 kinds 벡터에 저장
      /* Display the image */ // 이미지 표시
      //cv::imshow("CNN Classification ", imageList[i]); // OpenCV로 이미지를 화면에 보여줌 (주석 처리됨)
      //cv::waitKey(10000); // 10초 동안 키 입력 대기 (주석 처리됨)
    }
    imageList.clear(); // 이미지 리스트 초기화
    inputs.clear(); // 입력 버퍼 벡터 초기화
    outputs.clear(); // 출력 버퍼 벡터 초기화
  }
  delete[] FCResult; // FCResult 메모리 해제
  delete[] imageInputs; // imageInputs 메모리 해제
  delete[] softmax; // softmax 메모리 해제
}

/**
 * @brief Entry for running CNN
 *
 * @note Runner APIs prefixed with "dpu" are used to easily program &
 *       deploy CNN on DPU platform.
 *
 */
int main(int argc, char* argv[])
{
  // Check args // 인자 확인
  if (argc != 4) { // 인자가 4개가 아니면
    cout << "Usage: <executable> <xmodel> <test_images_dir>, <labels_filename>" << endl; // 사용법 출력
    return -1; // 종료
  }

  baseImagePath = std::string(argv[2]); //path name of the folder with test images // 테스트 이미지 폴더의 경로를 baseImagePath에 저장
  wordsPath     = std::string(argv[3]); //filename of the labels // 레이블 파일의 이름을 wordsPath에 저장

  auto graph = xir::Graph::deserialize(argv[1]); // xmodel 파일을 역직렬화하여 그래프 객체 생성
  auto subgraph = get_dpu_subgraph(graph.get()); // 그래프에서 DPU 서브그래프를 가져옴
  CHECK_EQ(subgraph.size(), 1u) // DPU 서브그래프가 하나뿐인지 확인
      << "CNN should have one and only one dpu subgraph.";
  LOG(INFO) << "create running for subgraph: " << subgraph[0]->get_name(); // DPU 서브그래프의 이름을 로그에 출력
  /*create runner*/ // 러너 생성
  auto runner = vart::Runner::create_runner(subgraph[0], "run"); // DPU 서브그래프를 이용하여 DPU 러너 생성
  // ai::XdpuRunner* runner = new ai::XdpuRunner("./"); // (주석 처리됨)
  /*get in/out tensor*/ // 입/출력 텐서 가져오기
  auto inputTensors = runner->get_input_tensors(); // 러너의 입력 텐서 벡터를 가져옴
  auto outputTensors = runner->get_output_tensors(); // 러너의 출력 텐서 벡터를 가져옴

  /*get in/out tensor shape*/ // 입/출력 텐서의 모양 가져오기
  int inputCnt = inputTensors.size(); // 입력 텐서의 개수
  int outputCnt = outputTensors.size(); // 출력 텐서의 개수
  TensorShape inshapes[inputCnt]; // 입력 텐서의 모양을 저장할 배열
  TensorShape outshapes[outputCnt]; // 출력 텐서의 모양을 저장할 배열
  shapes.inTensorList = inshapes; // shapes 구조체의 입력 텐서 리스트에 inshapes 할당
  shapes.outTensorList = outshapes; // shapes 구조체의 출력 텐서 리스트에 outshapes 할당
  getTensorShape(runner.get(), &shapes, inputCnt, outputCnt); // 러너와 shapes 구조체를 이용하여 텐서의 모양을 가져옴

  /*run with batch*/ // 배치 단위로 실행
  run_CNN(runner.get()); // 러너를 인자로 하여 run_CNN 함수 호출
  return 0; // 종료
}
	WARNING: Logging before InitGoogleLogging() is written to STDERR
	I20231011 14:42:20.506608 1925737 main_int8.cc:314] create running for subgraph: subgraph_quant_add
	XAIEFAL: INFO: Resource group Avail is created.
	XAIEFAL: INFO: Resource group Static is created.
	XAIEFAL: INFO: Resource group Generic is created.
	OUT  size 10
	IN   size 3072
	IN Height 32
	IN Width  32
	batchSize 14
	
	Image : truck_5790.png
	top[0] prob = 1.000000  name = truck
	top[1] prob = 0.000000  name = automobile
	top[2] prob = 0.000000  name = airplane
	top[3] prob = 0.000000  name = horse
	top[4] prob = 0.000000  name = ship
	
	Image : horse_543.png
	top[0] prob = 1.000000  name = horse
	top[1] prob = 0.000000  name = dog
	top[2] prob = 0.000000  name = cat
	top[3] prob = 0.000000  name = deer
	top[4] prob = 0.000000  name = frog
	
	Image : airplane_5544.png
	top[0] prob = 0.998793  name = airplane
	top[1] prob = 0.001169  name = cat
	top[2] prob = 0.000028  name = dog
	top[3] prob = 0.000006  name = horse
	top[4] prob = 0.000002  name = deer
	
	Image : horse_9091.png
	top[0] prob = 0.999998  name = horse
	top[1] prob = 0.000002  name = deer
	top[2] prob = 0.000001  name = dog
	top[3] prob = 0.000000  name = truck
	top[4] prob = 0.000000  name = automobile
	
	…
	
	Image : automobile_4598.png
	top[0] prob = 0.999942  name = automobile
	top[1] prob = 0.000058  name = truck
	top[2] prob = 0.000000  name = cat
	top[3] prob = 0.000000  name = frog
	top[4] prob = 0.000000  name = airplane

target/cifar10/run_all_cifar10_target.sh/run_cnn_cif10() 부분

# check DPU prediction accuracy
bash -x ./cifar10_performance.sh ${TARGET}
echo "PWD4 = " $PWD
cd ..
}

target/cifar10/cifar10_performance.sh 앞부분

#!/bin/bash

# Copyright © 2023 Advanced Micro Devices, Inc. All rights reserved.
# SPDX-License-Identifier: MIT

# Author: Daniele Bagni, Xilinx Inc
# date:  28 Apr. 2023


TARGET=$1

# check DPU prediction top1_accuracy
echo " "
echo " CIFAR10 RESNET18 TOP5 ACCURACY"
echo " "
python3 ./code/src/check_runtime_top5_cifar10.py -i ./rpt/predictions_cifar10_resnet18.log | tee ./rpt/results_predictions.log


echo " "
echo " CIFAR10 RESNET18 PERFORMANCE (fps)"
echo " "
./get_dpu_fps ./${TARGET}_train1_resnet18_cifar10.xmodel  1 10000  | tee  ./rpt/log1.txt  # 1 thread
./get_dpu_fps ./${TARGET}_train1_resnet18_cifar10.xmodel  2 10000  | tee  ./rpt/log2.txt  # 2 threads
./get_dpu_fps ./${TARGET}_train1_resnet18_cifar10.xmodel  3 10000  | tee  ./rpt/log3.txt  # 3 threads
#!/usr/bin/env python # 파이썬 실행 환경을 지정하는 특수 주석
# -*- coding: utf-8 -*- # 파이썬 스크립트의 인코딩을 utf-8로 지정하는 특수 주석

# Copyright © 2023 Advanced Micro Devices, Inc. All rights reserved.
# SPDX-License-Identifier: MIT # 저작권과 라이선스 정보

# Author: Daniele Bagni, Xilinx Inc # 저자 정보
# date:  28 Apr. 2023 # 작성 날짜

# ##################################################################################################

import warnings # 경고 메시지를 관리하는 모듈
warnings.filterwarnings("ignore", message="numpy.dtype size changed") # numpy.dtype size changed라는 경고 메시지를 무시하도록 설정
warnings.filterwarnings("ignore", message="numpy.ufunc size changed") # numpy.ufunc size changed라는 경고 메시지를 무시하도록 설정
import numpy as np # numpy 모듈을 np라는 별칭으로 임포트

from datetime import datetime # datetime 모듈에서 datetime 클래스를 임포트
import os # 운영체제와 상호작용하는 모듈
import argparse # 명령행 인자를 파싱하는 모듈

# construct the argument parse and parse the arguments # 인자 파서를 생성하고 인자를 파싱하는 코드
ap = argparse.ArgumentParser() # 인자 파서 객체 생성
ap.add_argument("-i", "--file",  required=True, help="input logfile") # -i 또는 --file로 입력받은 로그파일의 경로를 저장하는 인자 추가
ap.add_argument("-n", "--numel", default="5000", help="number of test images") # -n 또는 --numel로 입력받은 테스트 이미지의 개수를 저장하는 인자 추가, 기본값은 5000
args = vars(ap.parse_args()) # 인자 파서로 인자를 파싱하고 딕셔너리 형태로 변환하여 args에 저장

logfile = args["file"] # 로그파일의 경로를 logfile 변수에 저장
try: # 예외 처리를 위한 try 블록
    f = open(logfile, "r") # 로그파일을 읽기 모드로 열기
except IOError: # 파일 열기에 실패한 경우
    print("cannot open ", logfile) # 에러 메시지 출력
else: # 파일 열기에 성공한 경우
    lines = f.readlines() # 파일의 모든 줄을 읽어서 리스트로 저장
    tot_lines = len(lines) # 리스트의 길이를 tot_lines 변수에 저장
    print(logfile, " has ", tot_lines, " lines") # 로그파일의 줄 수 출력
    #f.seek(0) # 파일 포인터를 처음으로 이동
    f.close() # 파일 닫기


# ##################################################################################################

NUMEL = int(args["numel"]) # 테스트 이미지의 개수를 정수로 변환하여 NUMEL 변수에 저장

# initialize the label names for the CIFAR10 # CIFAR10 데이터셋의 레이블 이름을 초기화하는 코드
labelNames = { "airplane" : 0, "automobile" : 1, "bird" : 2, "cat" : 3, "deer" : 4, "dog" : 5,
                    "frog" : 6, "horse" : 7, "ship" : 8, "truck" : 9} # 레이블 이름과 인덱스를 매핑하는 딕셔너리 생성

# ##################################################################################################

top1_true  = 0 # top1 정확도를 위한 정답 개수를 저장하는 변수
top1_false = 0 # top1 정확도를 위한 오답 개수를 저장하는 변수
top5_true  = 0 # top5 정확도를 위한 정답 개수를 저장하는 변수
top5_false = 0 # top5 정확도를 위한 오답 개수를 저장하는 변수
img_count  = 0 # 이미지 개수를 저장하는 변수
false_pred = 0 # 잘못된 예측 개수를 저장하는 변수

test_ids = np.zeros(([NUMEL,1])) # 테스트 이미지의 실제 레이블을 저장하는 배열, 모든 원소를 0으로 초기화
preds    = np.zeros(([NUMEL, 1])) # 테스트 이미지의 예측 레이블을 저장하는 배열, 모든 원소를 0으로 초기화
idx = 0 # 인덱스를 저장하는 변수

for ln in range(0, tot_lines): # 로그파일의 모든 줄에 대해 반복
    if "Image" in lines[ln]: # 줄에 "Image"라는 문자열이 포함되어 있으면
        top5_lines = lines[ln:ln+6] # 해당 줄부터 다음 5줄까지를 top5_lines 변수에 저장
        filename= top5_lines[0].split("Image :")[1] # 첫 번째 줄에서 "Image :" 뒤의 부분을 filename 변수에 저장
        s2 = filename.index("_") # filename에서 "_"의 위치를 s2 변수에 저장
        class_name = filename[: s2].strip() # filename에서 "_" 앞의 부분을 공백을 제거하고 class_name 변수에 저장
        predicted = top5_lines[1].split("name = ")[1].strip() # 두 번째 줄에서 "name = " 뒤의 부분을 공백을 제거하고 predicted 변수에 저장
        if class_name in top5_lines[1]: # class_name이 두 번째 줄에 포함되어 있으면
            top1_true += 1 # top1 정답 개수를 1 증가
            top5_true += 1 # top5 정답 개수를 1 증가
        elif class_name in top5_lines[2]: # class_name이 세 번째 줄에 포함되어 있으면
            top5_true += 1 # top5 정답 개수를 1 증가
            top1_false +=1 # top1 오답 개수를 1 증가
        elif class_name in top5_lines[3]: # class_name이 네 번째 줄에 포함되어 있으면
            top5_true += 1 # top5 정답 개수를 1 증가
            top1_false +=1 # top1 오답 개수를 1 증가
        elif class_name in top5_lines[4]: # class_name이 다섯 번째 줄에 포함되어 있으면
            top5_true += 1 # top5 정답 개수를 1 증가
            top1_false +=1 # top1 오답 개수를 1 증가
        elif class_name in top5_lines[5]: # class_name이 여섯 번째 줄에 포함되어 있으면
            top5_true += 1 # top5 정답 개수를 1 증가
            top1_false +=1 # top1 오답 개수를 1 증가
        else: # class_name이 어느 줄에도 포함되어 있지 않으면
            top5_false += 1 # top5 오답 개수를 1 증가
            top1_false +=1 # top1 오답 개수를 1 증가
        test_ids[idx] = labelNames[class_name] # class_name에 해당하는 인덱스를 test_ids 배열의 idx번째 원소에 저장 # 실제 레이블 저장
        preds[idx]    = labelNames[predicted ] # predicted에 해당하는 인덱스를 preds 배열의 idx번째 원소에 저장 # 예측 레이블 저장
        img_count +=1 # 이미지 개수를 1 증가
        idx += 1 # 인덱스를 1 증가
        if ( idx == (NUMEL-1) ): # 인덱스가 테스트 이미지의 개수와 같으면
            break # 반복문 탈출
    else: # 줄에 "Image"라는 문자열이 포함되어 있지 않으면
        continue # 다음 줄로 넘어감

assert (top1_true+top1_false)  == img_count, "ERROR: top1 true+false not equal to the number of images" # top1 정답 개수와 오답 개수의 합이 이미지 개수와 같은지 확인, 아니면 에러 메시지 출력
assert (top5_true+top5_false)  == img_count, "ERROR: top5 true+false not equal to the number of images" # top5 정답 개수와 오답 개수의 합이 이미지 개수와 같은지 확인, 아니면 에러 메시지 출력

print("number of total images predicted ", img_count) # 전체 이미지 개수 출력
print("number of top1 false predictions ", top1_false) # top1 오답 개수 출력
print("number of top1 right predictions ", top1_true) # top1 정답 개수 출력
print("number of top5 false predictions ", top5_false) # top5 오답 개수 출력
print("number of top5 right predictions ", top5_true) # top5 정답 개수 출력

top1_accuracy = float(top1_true)/(top1_true+top1_false) # top1 정확도 계산
top5_accuracy = float(top5_true)/(top5_true+top5_false) # top5 정확도 계산

print("top1 accuracy = %.2f" % top1_accuracy) # top1 정확도 출력
print("top5 accuracy = %.2f" % top5_accuracy) # top5 정확도 출력
	 CIFAR10 RESNET18 TOP5 ACCURACY
	+ echo ' '
	
	+ tee ./rpt/results_predictions.log
	+ python3 ./code/src/check_runtime_top5_cifar10.py -i ./rpt/predictions_cifar10_resnet18.log
	./rpt/predictions_cifar10_resnet18.log  has  35008  lines
	number of total images predicted  4999
	number of top1 false predictions  816
	number of top1 right predictions  4183
	number of top5 false predictions  37
	number of top5 right predictions  4962
	top1 accuracy = 0.84
	top5 accuracy = 0.99

target/cifar10/cifar10_performance.sh 뒷부분

echo " "
echo " CIFAR10 RESNET18 PERFORMANCE (fps)"
echo " "
./get_dpu_fps ./${TARGET}_train1_resnet18_cifar10.xmodel  1 10000  | tee  ./rpt/log1.txt  # 1 thread
./get_dpu_fps ./${TARGET}_train1_resnet18_cifar10.xmodel  2 10000  | tee  ./rpt/log2.txt  # 2 threads
./get_dpu_fps ./${TARGET}_train1_resnet18_cifar10.xmodel  3 10000  | tee  ./rpt/log3.txt  # 3 threads
cat ./rpt/log1.txt ./rpt/log2.txt ./rpt/log3.txt >  ./rpt/${TARGET}_train1_resnet18_cifar10_results_fps.log
rm -f ./rpt/log?.txt

echo " "
/* # 저작권과 라이선스 정보
 * 
 * 저작권 © 2023 Advanced Micro Devices, Inc. All rights reserved.
 * SPDX-License-Identifier: MIT
 * 
 * # 저자 정보
 * 
 * 저자: Daniele Bagni, Xilinx Inc
 * 날짜:  28 Apr. 2023
 * 
 */

// 헤더 파일 임포트
#include <assert.h> // assert 매크로를 사용하기 위한 헤더 파일
#include <dirent.h> // 디렉토리 관련 함수를 사용하기 위한 헤더 파일
#include <stdio.h> // 표준 입출력 함수를 사용하기 위한 헤더 파일
#include <stdlib.h> // 표준 라이브러리 함수를 사용하기 위한 헤더 파일
#include <sys/stat.h> // 파일 상태 관련 함수를 사용하기 위한 헤더 파일
#include <unistd.h> // 유닉스 표준 함수를 사용하기 위한 헤더 파일
#include <chrono> // 시간 관련 라이브러리를 사용하기 위한 헤더 파일
#include <cassert> // assert 함수를 사용하기 위한 헤더 파일
#include <cmath> // 수학 관련 함수를 사용하기 위한 헤더 파일
#include <cstdio> // C 스타일 입출력 함수를 사용하기 위한 헤더 파일
#include <fstream> // 파일 입출력 스트림을 사용하기 위한 헤더 파일
#include <sstream> // 문자열 스트림을 사용하기 위한 헤더 파일
#include <iomanip> // 입출력 조작자를 사용하기 위한 헤더 파일
#include <iostream> // 표준 입출력 스트림을 사용하기 위한 헤더 파일
#include <queue> // 큐 컨테이너를 사용하기 위한 헤더 파일
#include <string> // 문자열 클래스를 사용하기 위한 헤더 파일
#include <vector> // 벡터 컨테이너를 사용하기 위한 헤더 파일
#include <thread> // 스레드 관련 라이브러리를 사용하기 위한 헤더 파일

#include "common.h" // 공통으로 사용하는 헤더 파일

using namespace std; // std 네임스페이스를 사용하기 위한 선언
using namespace std::chrono; // std::chrono 네임스페이스를 사용하기 위한 선언

GraphInfo shapes; // 그래프 정보를 저장하는 구조체 변수 선언

int num_threads   = 0; // 스레드 개수를 저장하는 정수형 변수 선언
int num_of_images = 0; // 이미지 개수를 저장하는 정수형 변수 선언
int num_images_x_thread = 0; // 스레드 당 이미지 개수를 저장하는 정수형 변수 선언

void runDPU(vart::Runner* runner, int8_t *imageInputs, int8_t *FCResult) // DPU를 실행하는 함수, 매개변수로 runner 객체, 이미지 입력 배열, FC 결과 배열을 받음
{
  // get in/out tensors and dims // 입력/출력 텐서와 차원을 가져오는 코드
  auto outputTensors = runner->get_output_tensors(); // runner 객체의 출력 텐서를 outputTensors 변수에 저장
  auto inputTensors = runner->get_input_tensors(); // runner 객체의 입력 텐서를 inputTensors 변수에 저장
  auto out_dims = outputTensors[0]->get_dims(); // 첫 번째 출력 텐서의 차원을 out_dims 변수에 저장
  auto in_dims = inputTensors[0]->get_dims(); // 첫 번째 입력 텐서의 차원을 in_dims 변수에 저장
  int batchSize = in_dims[0]; // 입력 텐서의 첫 번째 차원을 batchSize 변수에 저장
  int outSize   = shapes.outTensorList[0].size; // shapes 구조체의 첫 번째 출력 텐서의 크기를 outSize 변수에 저장
  int inSize    = shapes.inTensorList[0].size; // shapes 구조체의 첫 번째 입력 텐서의 크기를 inSize 변수에 저장
  std::vector<std::unique_ptr<vart::TensorBuffer>> inputs, outputs; // 입력/출력 텐서 버퍼를 저장하는 벡터 생성
  std::vector<vart::TensorBuffer*> inputsPtr, outputsPtr; // 입력/출력 텐서 버퍼의 포인터를 저장하는 벡터 생성
  std::vector<std::shared_ptr<xir::Tensor>> batchTensors; // 배치 텐서를 저장하는 벡터 생성
  int8_t *loc_imageInputs = imageInputs; // 이미지 입력 배열의 포인터를 loc_imageInputs 변수에 저장
  int8_t *loc_FCResult    = FCResult; // FC 결과 배열의 포인터를 loc_FCResult 변수에 저장
  for (unsigned int n = 0; n < num_images_x_thread; n += batchSize) //this works correctly for either batchSize= 1 or 3 // 스레드 당 이미지 개수만큼 반복, 배치 크기만큼 증가
  {

    loc_imageInputs = imageInputs+n * inSize; // 이미지 입력 배열의 n번째 배치 위치를 loc_imageInputs에 저장
    loc_FCResult    = FCResult   +n * outSize; // FC 결과 배열의 n번째 배치 위치를 loc_FCResult에 저장
    // in/out tensor refactory for batch inout/output // 배치 입력/출력을 위한 텐서 재구성 코드
    batchTensors.push_back(std::shared_ptr<xir::Tensor>(xir::Tensor::create(inputTensors[0]->get_name(), // 첫 번째 입력 텐서의 이름과 차원, 데이터 타입으로 새로운 텐서를 생성하고 배치 텐서 벡터에 추가
          in_dims, xir::DataType{xir::DataType::XINT, 8u})));
    inputs.push_back(std::make_unique<CpuFlatTensorBuffer>(loc_imageInputs, batchTensors.back().get())); // loc_imageInputs와 마지막 배치 텐서로 새로운 텐서 버퍼를 생성하고 입력 텐서 버퍼 벡터에 추가
    batchTensors.push_back(std::shared_ptr<xir::Tensor>(xir::Tensor::create(outputTensors[0]->get_name(), // 첫 번째 출력 텐서의 이름과 차원, 데이터 타입으로 새로운 텐서를 생성하고 배치 텐서 벡터에 추가
          out_dims,xir::DataType{xir::DataType::XINT, 8u})));
    outputs.push_back(std::make_unique<CpuFlatTensorBuffer>( loc_FCResult, batchTensors.back().get())); // loc_FCResult와 마지막 배치 텐서로 새로운 텐서 버퍼를 생성하고 출력 텐서 버퍼 벡터에 추가
    //tensor buffer input/output // 텐서 버퍼 입력/출력 코드
    inputsPtr.clear(); // 입력 텐서 버퍼 포인터 벡터를 비움
    outputsPtr.clear(); // 출력 텐서 버퍼 포인터 벡터를 비움
    inputsPtr.push_back(inputs[0].get()); // 첫 번째 입력 텐서 버퍼의 포인터를 입력 텐서 버퍼 포인터 벡터에 추가
    outputsPtr.push_back(outputs[0].get()); // 첫 번째 출력 텐서 버퍼의 포인터를 출력 텐서 버퍼 포인터 벡터에 추가
    //run // 실행 코드
    auto job_id = runner->execute_async(inputsPtr, outputsPtr); // runner 객체의 비동기 실행 메서드를 호출하고 작업 아이디를 job_id 변수에 저장
    runner->wait(job_id.first, -1); // runner 객체의 대기 메서드를 호출하고 작업 완료를 기다림
    inputs.clear(); // 입력 텐서 버퍼 벡터를 비움
    outputs.clear(); // 출력 텐서 버퍼 벡터를 비움
  }
}

int main(int argc, char* argv[]) // 메인 함수, 매개변수로 명령행 인자의 개수와 값들을 받음
{

  // Check args // 인자를 확인하는 코드
  if (argc != 4) { // 인자의 개수가 4가 아니면
    cout << "Usage: get_dpu_fps xmodel_pathname num_of_threads(from 1 to 6) num_of_images" << endl; // 사용법을 출력
    return -1; // -1을 반환하고 종료
  }
  num_threads   = atoi(argv[2]); // 두 번째 인자를 정수로 변환하여 num_threads 변수에 저장
  assert( (num_threads<=6)&(num_threads>=1) ); // num_threads가 1 이상 6 이하인지 확인, 아니면 에러 발생
  num_of_images = atoi(argv[3]); // 세 번째 인자를 정수로 변환하여 num_of_images 변수에 저장

  for (int i = 0; i< argc; i++) // 인자의 개수만큼 반복
    cout << argv[i] << " "; // 인자의 값을 공백으로 구분하여 출력
  cout << endl; // 개행 출력

  /////////////////////////////////////////////////////////////////////////////////////////////
  // PREPARE DPU STUFF // DPU 관련 준비 작업을 하는 코드

  auto graph = xir::Graph::deserialize(argv[1]); // 첫 번째 인자로 받은 xmodel 파일을 역직렬화하여 그래프 객체를 생성
  auto subgraph = get_dpu_subgraph(graph.get()); // 그래프 객체에서 DPU 서브그래프를 가져오는 함수 호출
  CHECK_EQ(subgraph.size(), 1u) // 서브그래프의 개수가 1인지 확인, 아니면 에러 메시지 출력
      << "CNN should have one and only one dpu subgraph.";
  LOG(INFO) << "create running for subgraph: " << subgraph[0]->get_name(); // 서브그래프의 이름을 로그로 출력

  //create up to 6 runners // 최대 6개의 러너 객체를 생성하는 코드
  auto runner  = vart::Runner::create_runner(subgraph[0], "run"); // 첫 번째 서브그래프로 러너 객체를 생성하고 runner 변수에 저장
  auto runner1 = vart::Runner::create_runner(subgraph[0], "run"); // 첫 번째 서브그래프로 러너 객체를 생성하고 runner1 변수에 저장
  auto runner2 = vart::Runner::create_runner(subgraph[0], "run"); // 첫 번째 서브그래프로 러너 객체를 생성하고 runner2 변수에 저장
  auto runner3 = vart::Runner::create_runner(subgraph[0], "run"); // 첫 번째 서브그래프로 러너 객체를 생성하고 runner3 변수에 저장
  auto runner4 = vart::Runner::create_runner(subgraph[0], "run"); // 첫 번째 서브그래프로 러너 객체를 생성하고 runner4 변수에 저장
  auto runner5 = vart::Runner::create_runner(subgraph[0], "run"); // 첫 번째 서브그래프로 러너 객체를 생성하고 runner5 변수에 저장

  // get in/out tensors and dims // 입력/출력 텐서와 차원을 가져오는 코드
  auto inputTensors = runner->get_input_tensors(); // runner 객체의 입력 텐서를 inputTensors 변수에 저장
  auto outputTensors = runner->get_output_tensors(); // runner 객체의 출력 텐서를 outputTensors 변수에 저장
  auto out_dims = outputTensors[0]->get_shape(); // 첫 번째 출력 텐서의 차원을 out_dims 변수에 저장
  auto in_dims = inputTensors[0]->get_shape(); // 첫 번째 입력 텐서의 차원을 in_dims 변수에 저장

  // get in/out tensor shape // 입력/출력 텐서의 모양을 가져오는 코드
  int inputCnt = inputTensors.size(); // 입력 텐서의 개수를 inputCnt 변수에 저장
  int outputCnt = outputTensors.size(); // 출력 텐서의 개수를 outputCnt 변수에 저장
  TensorShape inshapes[inputCnt]; // 입력 텐서의 모양을 저장하는 배열 선언
  TensorShape outshapes[outputCnt]; // 출력 텐서의 모양을 저장하는 배열 선언
  shapes.inTensorList = inshapes; // shapes 구조체의 입력 텐서 리스트에 inshapes 배열을 할당
  shapes.outTensorList = outshapes; // shapes 구조체의 출력 텐서 리스트에 outshapes 배열을 할당
  getTensorShape(runner.get(), &shapes, inputCnt, outputCnt); // runner 객체와 shapes 구조체, 입력/출력 텐서의 개수를 인자로 하여 텐서 모양을 가져오는 함수 호출

  // get shape info // 모양 정보를 가져오는 코드
  int outSize   = shapes.outTensorList[0].size; // shapes 구조체의 첫 번째 출력 텐서의 크기를 outSize 변수에 저장
  int outHeight = shapes.outTensorList[0].height; // shapes 구조체의 첫 번째 출력 텐서의 높이를 outHeight 변수에 저장
  int outWidth  = shapes.outTensorList[0].width; // shapes 구조체의 첫 번째 출력 텐서의 너비를 outWidth 변수에 저장
  int inSize = shapes.inTensorList[0].size; // shapes 구조체의 첫 번째 입력 텐서의 크기를 inSize 변수에 저장
  int inHeight = shapes.inTensorList[0].height; // shapes 구조체의 첫 번째 입력 텐서의 높이를 inHeight 변수에 저장
  int inWidth = shapes.inTensorList[0].width; // shapes 구조체의 첫 번째 입력 텐서의 너비를 inWidth 변수에 저장
  int batchSize = in_dims[0]; // 입력 텐서의 첫 번째 차원을 batchSize 변수에 저장
  int num_of_classes = outSize / (outHeight * outWidth); // 출력 텐서의 크기를 높이와 너비로 나누어 클래스의 개수를 num_of_classes 변수에 저장

  //scaling factors // 스케일링 인자를 계산하는 코드
  //int out_fixpos = (outputTensors[0])->template get_attr<int>("fix_point"); // 첫 번째 출력 텐서의 고정 소수점 위치를 out_fixpos 변수에 저장
  //auto out_fix_scale = std::exp2f(1.0f * (float)out_fixpos); // 2의 out_fixpos 제곱을 out_fix_scale 변수에 저장
  //cout << "outS     " << out_fix_scale << endl; // out_fix_scale 값을 출력
  //int in_fixpos = (inputTensors[0])->template get_attr<int>("fix_point"); // 첫 번째 입력 텐서의 고정 소수점 위치를 in_fixpos 변수에 저장
  //auto in_fix_scale = std::exp2f(1.0f * (float)in_fixpos); // 2의 in_fixpos 제곱을 in_fix_scale 변수에 저장
  //cout << "inP      " << in_fixpos << endl; // in_fixpos 값을 출력
  //cout << "inS      " << in_fix_scale << endl; // in_fix_scale 값을 출력
  auto input_scale = get_input_scale(inputTensors[0]); // 첫 번째 입력 텐서의 스케일 값을 가져오는 함수 호출
  auto output_scale = get_output_scale(outputTensors[0]); // 첫 번째 출력 텐서의 스케일 값을 가져오는 함수 호출
// debug messages // 디버그 메시지를 출력하는 코드
  cout << "outSize   " << outSize << endl; // 출력 텐서의 크기 출력
  cout << "inSize    " << inSize << endl; // 입력 텐서의 크기 출력
  cout << "outW      " << outWidth << endl; // 출력 텐서의 너비 출력
  cout << "outH      " << outHeight << endl; // 출력 텐서의 높이 출력
  cout << "inpW      " << inWidth << endl; // 입력 텐서의 너비 출력
  cout << "inpH      " << inHeight << endl; // 입력 텐서의 높이 출력
  cout << "inp scale " << input_scale << endl; // 입력 텐서의 스케일 값 출력
  cout << "out scale " << output_scale << endl; // 출력 텐서의 스케일 값 출력
  cout << "# classes " << num_of_classes << endl; // 클래스의 개수 출력
  cout << "batchSize " << batchSize << endl; // 배치 크기 출력

    /////////////////////////////////////////////////////////////////////////////////////////////
  // TIMERS CALIBRATION // 타이머 보정을 하는 코드

  int num_of_trials = 200; // 시행 횟수를 200으로 설정
  std::chrono::duration<double, std::micro> avg_calibr_highres(0); // 평균 보정 시간을 저장할 변수 선언
  for (int i =0; i<num_of_trials; i++) // 시행 횟수만큼 반복
  {
      auto t1 = std::chrono::high_resolution_clock::now(); // 현재 시간을 t1 변수에 저장
      auto t2 = std::chrono::high_resolution_clock::now(); // 현재 시간을 t2 변수에 저장
      // floating-point duration: no duration_cast needed
      std::chrono::duration<double, std::micro> fp_us = t2 - t1; // t2와 t1의 차이를 마이크로초 단위로 fp_us 변수에 저장
      avg_calibr_highres  += fp_us; // fp_us 값을 avg_calibr_highres에 누적
      //if (i%10 ==0) cout << "[Timers calibration  ] " << fp_us.count() << "us" << endl; // 10번마다 fp_us 값을 출력하는 코드 (주석 처리됨)
    }
  cout << "[average calibration high resolution clock] " << avg_calibr_highres.count() / num_of_trials << "us"  << endl; // 평균 보정 시간을 출력
  cout << "\n" << endl;

  /////////////////////////////////////////////////////////////////////////////////////////////
  // MEMORY ALLOCATION // 메모리 할당을 하는 코드

  //number of images per thread // 스레드 당 이미지 개수를 계산하는 코드
  num_images_x_thread = num_of_images/num_threads; // 전체 이미지 개수를 스레드 개수로 나누어 num_images_x_thread 변수에 저장
  num_images_x_thread = (num_images_x_thread/batchSize)*batchSize; // num_images_x_thread를 배치 크기로 나누고 다시 곱하여 배치 크기의 배수로 만듦
  cout << "\n number of dummy images per thread: " << num_images_x_thread << endl; // 스레드 당 이미지 개수를 출력
  //effective number of images as multiple of num_threads and batchSize // 스레드 개수와 배치 크기의 배수로 효과적인 이미지 개수를 계산하는 코드
  num_of_images = num_images_x_thread * num_threads; // num_images_x_thread에 스레드 개수를 곱하여 num_of_images 변수에 저장

  // memory allocation // 메모리 할당을 하는 코드
  int8_t * imageInputs = new int8_t [(num_of_images)*inSize]; // 이미지 입력을 저장할 동적 배열을 생성하고 imageInputs 변수에 저장
  int8_t * FCResult    = new int8_t [(num_of_images)*outSize]; // FC 결과를 저장할 동적 배열을 생성하고 FCResult 변수에 저장
  cout << "\n allocated " << num_of_images* inSize << " bytes for  input buffer " << endl; // 입력 버퍼에 할당된 바이트 수를 출력
  cout << "\n allocated " << num_of_images*outSize << " bytes for output buffer " << endl; // 출력 버퍼에 할당된 바이트 수를 출력

    /////////////////////////////////////////////////////////////////////////////////////////////
  // split dummy images in chunks, each chunks for its own thead // 더미 이미지를 스레드 별로 나누는 코드
  int8_t  *imagesInput0 = imageInputs+ inSize*(num_threads==1 ? 0*num_images_x_thread : 0); // imageInputs 배열에서 첫 번째 스레드의 이미지 입력 위치를 imagesInput0 변수에 저장
  int8_t  *imagesInput1 = imageInputs+ inSize*(num_threads==2 ? 1*num_images_x_thread : 0); // imageInputs 배열에서 두 번째 스레드의 이미지 입력 위치를 imagesInput1 변수에 저장
  int8_t  *imagesInput2 = imageInputs+ inSize*(num_threads==3 ? 2*num_images_x_thread : 0); // imageInputs 배열에서 세 번째 스레드의 이미지 입력 위치를 imagesInput2 변수에 저장
  int8_t  *imagesInput3 = imageInputs+ inSize*(num_threads==4 ? 3*num_images_x_thread : 0); // imageInputs 배열에서 네 번째 스레드의 이미지 입력 위치를 imagesInput3 변수에 저장
  int8_t  *imagesInput4 = imageInputs+ inSize*(num_threads==5 ? 4*num_images_x_thread : 0); // imageInputs 배열에서 다섯 번째 스레드의 이미지 입력 위치를 imagesInput4 변수에 저장
  int8_t  *imagesInput5 = imageInputs+ inSize*(num_threads==6 ? 5*num_images_x_thread : 0); // imageInputs 배열에서 여섯 번째 스레드의 이미지 입력 위치를 imagesInput5 변수에 저장

  int8_t  *FCResult0    = FCResult+   outSize*(num_threads==1 ? 0*num_images_x_thread : 0); // FCResult 배열에서 첫 번째 스레드의 FC 결과 위치를 FCResult0 변수에 저장
  int8_t  *FCResult1    = FCResult+   outSize*(num_threads==2 ? 1*num_images_x_thread : 0); // FCResult 배열에서 두 번째 스레드의 FC 결과 위치를 FCResult1 변수에 저장
  int8_t  *FCResult2    = FCResult+   outSize*(num_threads==3 ? 2*num_images_x_thread : 0); // FCResult 배열에서 세 번째 스레드의 FC 결과 위치를 FCResult2 변수에 저장
  int8_t  *FCResult3    = FCResult+   outSize*(num_threads==4 ? 3*num_images_x_thread : 0); // FCResult 배열에서 네 번째 스레드의 FC 결과 위치를 FCResult3 변수에 저장
  int8_t  *FCResult4    = FCResult+   outSize*(num_threads==5 ? 4*num_images_x_thread : 0); // FCResult 배열에서 다섯 번째 스레드의 FC 결과 위치를 FCResult4 변수에 저장
  int8_t  *FCResult5    = FCResult+   outSize*(num_threads==6 ? 5*num_images_x_thread : 0); // FCResult 배열에서 여섯 번째 스레드의 FC 결과 위치를 FCResult5 변수에 저장
    
/////////////////////////////////////////////////////////////////////////////////////////////
  // MULTITHREADING DPU EXECUTION WITH BATCH // 배치 단위로 DPU를 병렬 실행하는 코드
  thread workers[num_threads]; // 스레드 배열을 선언하고 num_threads 크기로 초기화

  //t_start = system_clock::now(); // 시스템 시간을 t_start 변수에 저장하는 코드 (주석 처리됨)
  auto dpu_t1 = std::chrono::high_resolution_clock::now(); // 고해상도 시간을 dpu_t1 변수에 저장

    for (auto i = 0; i < num_threads; i++) // 스레드 개수만큼 반복
    {
        if (i == 0) workers[i] = thread(runDPU, runner.get(),   ref(imagesInput0), ref(FCResult0) ); // 첫 번째 스레드를 생성하고 runDPU 함수를 호출하며 runner, imagesInput0, FCResult0을 인자로 전달
        if (i == 1) workers[i] = thread(runDPU, runner1.get(),  ref(imagesInput1), ref(FCResult1) ); // 두 번째 스레드를 생성하고 runDPU 함수를 호출하며 runner1, imagesInput1, FCResult1을 인자로 전달
        if (i == 2) workers[i] = thread(runDPU, runner2.get(),  ref(imagesInput2), ref(FCResult2) ); // 세 번째 스레드를 생성하고 runDPU 함수를 호출하며 runner2, imagesInput2, FCResult2을 인자로 전달
        if (i == 3) workers[i] = thread(runDPU, runner3.get(),  ref(imagesInput3), ref(FCResult3) ); // 네 번째 스레드를 생성하고 runDPU 함수를 호출하며 runner3, imagesInput3, FCResult3을 인자로 전달
        if (i == 4) workers[i] = thread(runDPU, runner4.get(),  ref(imagesInput4), ref(FCResult4) ); // 다섯 번째 스레드를 생성하고 runDPU 함수를 호출하며 runner4, imagesInput4, FCResult4을 인자로 전달
        if (i == 5) workers[i] = thread(runDPU, runner5.get(),  ref(imagesInput5), ref(FCResult5) ); // 여섯 번째 스레드를 생성하고 runDPU 함수를 호출하며 runner5, imagesInput5, FCResult5을 인자로 전달
    }
    // Release thread resources. // 스레드 자원을 해제하는 코드
    for (auto &w : workers) { // 스레드 배열의 각 원소에 대해 반복
      if (w.joinable()) w.join(); // 스레드가 종료될 때까지 대기하고 스레드를 종료
    }

    auto dpu_t2 = std::chrono::high_resolution_clock::now(); // 고해상도 시간을 dpu_t2 변수에 저장
    std::chrono::duration<double, std::micro> dpu_time = dpu_t2 - dpu_t1 - avg_calibr_highres; // dpu_t2와 dpu_t1의 차이에서 평균 보정 시간을 빼서 dpu_time 변수에 저장
    cout << "\n" << endl; // 개행 출력
    double dpu_tot_time = (double) dpu_time.count(); // dpu_time의 값을 double 형으로 변환하여 dpu_tot_time 변수에 저장
    double dpu_avg_time = (dpu_tot_time*1000000.0)/num_of_images; //us // dpu_tot_time에 백만을 곱하고 이미지 개수로 나누어 dpu_avg_time 변수에 저장
    double dpu_avg_fps  = (num_of_images*1000000.0)/dpu_tot_time; // 이미지 개수에 백만을 곱하고 dpu_tot_time으로 나누어 dpu_avg_fps 변수에 저장
    cout << "[DPU tot Time ] " << dpu_tot_time  << "us" << endl; // DPU 총 시간을 출력
    cout << "[DPU avg Time ] " << dpu_avg_time  << "us" << endl; // DPU 평균 시간을 출력
    cout << "[DPU avg FPS  ] " << dpu_avg_fps   << endl; // DPU 평균 FPS를 출력
    cout << "\n" << endl; // 개행 출력

    /////////////////////////////////////////////////////////////////////////////////////////////

    cout << "deleting memory buffer" << endl; // 메모리 버퍼를 삭제한다는 메시지 출력
    delete[] imageInputs; // imageInputs 배열을 삭제
    delete[] FCResult; // FCResult 배열을 삭제

    return 0; // 0을 반환하고 종료
  }
	+ ./get_dpu_fps ./vek280_train1_resnet18_cifar10.xmodel 2 10000
	+ tee ./rpt/log2.txt
	./get_dpu_fps ./vek280_train1_resnet18_cifar10.xmodel 2 10000
	WARNING: Logging before InitGoogleLogging() is written to STDERR
	I20231011 14:42:26.378609 1926763 get_dpu_fps.cc:107] create running for subgraph: subgraph_quant_add
	XAIEFAL: INFO: Resource group Avail is created.
	XAIEFAL: INFO: Resource group Static is created.
	XAIEFAL: INFO: Resource group Generic is created.
	outSize   10
	inSize    3072
	outW      1
	outH      1
	inpW      32
	inpH      32
	inp scale 64
	out scale 0.25
	# classes 10
	batchSize 14
	[average calibration high resolution clock] 0.063us
	
	
	
	 number of dummy images per thread: 4998
	
	 allocated 30707712 bytes for  input buffer
	
	 allocated 99960 bytes for output buffer
	
	
	[DPU tot Time ] 590140us
	[DPU avg Time ] 5.90376e+07us
	[DPU avg FPS  ] 16938.4
	
	
	deleting memory buffer
	+ tee ./rpt/log3.txt
	+ ./get_dpu_fps ./vek280_train1_resnet18_cifar10.xmodel 3 10000
	./get_dpu_fps ./vek280_train1_resnet18_cifar10.xmodel 3 10000
	WARNING: Logging before InitGoogleLogging() is written to STDERR
	I20231011 14:42:27.949460 1926847 get_dpu_fps.cc:107] create running for subgraph: subgraph_quant_add
	XAIEFAL: INFO: Resource group Avail is created.
	XAIEFAL: INFO: Resource group Static is created.
	XAIEFAL: INFO: Resource group Generic is created.
	outSize   10
	inSize    3072
	outW      1
	outH      1
	inpW      32
	inpH      32
	inp scale 64
	out scale 0.25
	# classes 10
	batchSize 14
	[average calibration high resolution clock] 0.06015us
	
	
	
	 number of dummy images per thread: 3332
	
	 allocated 30707712 bytes for  input buffer
	
	 allocated 99960 bytes for output buffer
	
	
	[DPU tot Time ] 538336us
	[DPU avg Time ] 5.38551e+07us
	[DPU avg FPS  ] 18568.3
	
	
	deleting memory buffer
	+ cat ./rpt/log1.txt ./rpt/log2.txt ./rpt/log3.txt
	+ rm -f ./rpt/log1.txt ./rpt/log2.txt ./rpt/log3.txt
	+ echo ' '
	
	PWD4 =  /home/root/target_vek280/cifar10
	
	end of cifar10
	
	PWD5 =  /home/root/target_vek280
	
	clean imagenet
	
	
	compile imagenet
	
	PWD1 =  /home/root/target_vek280/imagenet/code_resnet50
	++ dirname ./build_resnet50.sh
	+ cd .
	+ CXX=g++
	++ sed 's/^.*:\s*//'
	++ lsb_release -a
	++ grep 'Distributor ID'
	+ os=petalinux
	++ sed 's/^.*:\s*//'
	++ lsb_release -a
	++ grep Release
	+ os_version=2023.1+release-S05010539
	++ uname -p
	+ arch=unknown
	+ target_info=petalinux.2023.1+release-S05010539.unknown
	+ install_prefix_default=/home/root/.local/petalinux.2023.1+release-S05010539.unknown
	+ g++ --version
	g++ (GCC) 12.2.0
	Copyright (C) 2022 Free Software Foundation, Inc.
	This is free software; see the source for copying conditions.  There is NO
	warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
	
	+ result=0
	+ grep opencv4
	+ pkg-config --list-all
	opencv4                             OpenCV - Open Source Computer Vision Library
	+ result=1
	+ '[' 1 -eq 1 ']'
	++ pkg-config --cflags --libs-only-L opencv4
	+ OPENCV_FLAGS=-I/usr/include/opencv4
	++ basename /home/root/target_vek280/imagenet/code_resnet50
	+ name=code_resnet50
	+ [[ g++ == *\s\y\s\r\o\o\t* ]]
	+ g++ -O2 -fno-inline -I. -I/home/root/.local/petalinux.2023.1+release-S05010539.unknown.Debug/include -I/home/root/.local/petalinux.2023.1+release-S05010539.unknown.Release/include -L/home/root/.local/petalinux.2023.1+release-S05010539.unknown.Debug/lib -L/home/root/.local/petalinux.2023.1+release-S05010539.unknown.Release/lib -Wl,-rpath=/home/root/.local/petalinux.2023.1+release-S05010539.unknown.Debug/lib -Wl,-rpath=/home/root/.local/petalinux.2023.1+release-S05010539.unknown.Release/lib -I/home/root/target_vek280/imagenet/code_resnet50/../../common -o code_resnet50 -std=c++17 /home/root/target_vek280/imagenet/code_resnet50/src/main_resnet50.cc /home/root/target_vek280/imagenet/code_resnet50/../../common/common.cpp -Wl,-rpath=/home/root/target_vek280/imagenet/code_resnet50/lib -lvart-runner -I/usr/include/opencv4 -lopencv_videoio -lopencv_imgcodecs -lopencv_highgui -lopencv_imgproc -lopencv_core -lglog -lxir -lunilog -lpthread
	PWD2 =  /home/root/target_vek280
	
	build imagenet test images
	
	
	PWD3 =  /home/root/target_vek280
	
	run resnet50 CNN
	
	WARNING: Logging before InitGoogleLogging() is written to STDERR
	I20231011 14:43:02.777024 1927131 main_resnet50.cc:342] create running for subgraph: subgraph_quant_avg_pool_fix(TransferPoolFixToDwConv2dFix)
	XAIEFAL: INFO: Resource group Avail is created.
	XAIEFAL: INFO: Resource group Static is created.
	XAIEFAL: INFO: Resource group Generic is created.
	OUT  size 1000
	IN   size 150528
	IN Height 224
	IN Width  224
	batchSize 14
	
	Image : ILSVRC2012_val_00049764.JPEG out_result = 18 out index = 409
	top[0] prob = 0.849117  name = analog clock
	top[1] prob = 0.147554  name = wall clock
	top[2] prob = 0.001277  name = bell cote, bell cot
	top[3] prob = 0.000774  name = barometer
	top[4] prob = 0.000470  name = restaurant, eating house, eating place, eatery
	
	Image : ILSVRC2012_val_00049670.JPEG out_result = 21.75 out index = 476
	top[0] prob = 0.999958  name = carousel, carrousel, merry-go-round, roundabout, whirligig
	top[1] prob = 0.000017  name = shoe shop, shoe-shop, shoe store
	top[2] prob = 0.000005  name = wig
	top[3] prob = 0.000002  name = lampshade, lamp shade
	top[4] prob = 0.000002  name = drum, membranophone, tympan
	
	…
	
	Image : ILSVRC2012_val_00049798.JPEG out_result = 15.25 out index = 794
	top[0] prob = 0.873021  name = shower curtain
	top[1] prob = 0.033851  name = binder, ring-binder
	top[2] prob = 0.015990  name = toilet seat
	top[3] prob = 0.007553  name = envelope
	top[4] prob = 0.005882  name = menu
	
	Image : ILSVRC2012_val_00049954.JPEG out_result = 12.5 out index = 289
	top[0] prob = 0.548879  name = snow leopard, ounce, Panthera uncia
	top[1] prob = 0.157256  name = puffer, pufferfish, blowfish, globefish
	top[2] prob = 0.095381  name = leopard, Panthera pardus
	top[3] prob = 0.027327  name = hen-of-the-woods, hen of the woods, Polyporus frondosus, Grifola frondosa
	top[4] prob = 0.021282  name = African crocodile, Nile crocodile, Crocodylus niloticus
	+ TARGET=vek280
	+ echo ' '
	
	+ echo ' IMAGENET RESNET50 TOP1 ACCURACY ON DPU'
	 IMAGENET RESNET50 TOP1 ACCURACY ON DPU
	+ echo ' '
	
	+ tee resnet50_result_predictions.log
	+ python3 ./code_resnet50/src/check_runtime_top1_imagenet.py -i ./rpt/predictions_resnet50_imagenet.log
	./rpt/predictions_resnet50_imagenet.log  has  3510  lines
	number of total images predicted  499
	number of top1 false predictions  151
	number of top1 right predictions  348
	top1 accuracy = 0.70
	+ echo ' '
	
	+ echo ' '
	
	+ echo ' IMAGENET RESNET18 TOP1 ACCURACY ON DPU'
	 IMAGENET RESNET18 TOP1 ACCURACY ON DPU
	+ echo ' '
	
	+ python3 ./code_resnet50/src/check_runtime_top1_imagenet.py -i ./rpt/predictions_resnet18_imagenet.log
	+ tee resnet18_result_predictions.log
	cannot open  ./rpt/predictions_resnet18_imagenet.log
	Traceback (most recent call last):
	  File "/home/root/target_vek280/imagenet/./code_resnet50/src/check_runtime_top1_imagenet.py", line 61, in <module>
	    for ln in range(0, tot_lines):
	NameError: name 'tot_lines' is not defined
	+ echo ' '
	
	+ echo ' '
	
	+ echo ' IMAGENET RESNET18 PERFORMANCE (fps)'
	 IMAGENET RESNET18 PERFORMANCE (fps)
	+ echo ' '
	
	+ ./get_dpu_fps ./vek280_resnet18_imagenet.xmodel 1 1000
	+ tee ./rpt/log1.txt
	./get_dpu_fps ./vek280_resnet18_imagenet.xmodel 1 1000
	WARNING: Logging before InitGoogleLogging() is written to STDERR
	I20231011 14:43:12.314563 1927193 get_dpu_fps.cc:107] create running for subgraph: subgraph_quant_add
	XAIEFAL: INFO: Resource group Avail is created.
	XAIEFAL: INFO: Resource group Static is created.
	XAIEFAL: INFO: Resource group Generic is created.
	outSize   1000
	inSize    150528
	outW      1
	outH      1
	inpW      224
	inpH      224
	inp scale 0.25
	out scale 0.25
	# classes 1000
	batchSize 14
	[average calibration high resolution clock] 0.0809us
	
	
	
	 number of dummy images per thread: 994
	
	 allocated 149624832 bytes for  input buffer
	
	 allocated 994000 bytes for output buffer
	
	
	[DPU tot Time ] 240645us
	[DPU avg Time ] 2.42098e+08us
	[DPU avg FPS  ] 4130.56
	
	
	deleting memory buffer
	+ ./get_dpu_fps ./vek280_resnet18_imagenet.xmodel 2 1000
	+ tee ./rpt/log2.txt
	./get_dpu_fps ./vek280_resnet18_imagenet.xmodel 2 1000
	WARNING: Logging before InitGoogleLogging() is written to STDERR
	I20231011 14:43:13.393136 1927203 get_dpu_fps.cc:107] create running for subgraph: subgraph_quant_add
	XAIEFAL: INFO: Resource group Avail is created.
	XAIEFAL: INFO: Resource group Static is created.
	XAIEFAL: INFO: Resource group Generic is created.
	outSize   1000
	inSize    150528
	outW      1
	outH      1
	inpW      224
	inpH      224
	inp scale 0.25
	out scale 0.25
	# classes 1000
	batchSize 14
	[average calibration high resolution clock] 0.0808us
	
	
	
	 number of dummy images per thread: 490
	
	 allocated 147517440 bytes for  input buffer
	
	 allocated 980000 bytes for output buffer
	
	
	[DPU tot Time ] 133378us
	[DPU avg Time ] 1.361e+08us
	[DPU avg FPS  ] 7347.52
	
	
	deleting memory buffer
	+ tee ./rpt/log3.txt
	+ ./get_dpu_fps ./vek280_resnet18_imagenet.xmodel 3 1000
	./get_dpu_fps ./vek280_resnet18_imagenet.xmodel 3 1000
	WARNING: Logging before InitGoogleLogging() is written to STDERR
	I20231011 14:43:14.402565 1927214 get_dpu_fps.cc:107] create running for subgraph: subgraph_quant_add
	XAIEFAL: INFO: Resource group Avail is created.
	XAIEFAL: INFO: Resource group Static is created.
	XAIEFAL: INFO: Resource group Generic is created.
	outSize   1000
	inSize    150528
	outW      1
	outH      1
	inpW      224
	inpH      224
	inp scale 0.25
	out scale 0.25
	# classes 1000
	batchSize 14
	[average calibration high resolution clock] 0.081us
	
	
	
	 number of dummy images per thread: 322
	
	 allocated 145410048 bytes for  input buffer
	
	 allocated 966000 bytes for output buffer
	
	
	[DPU tot Time ] 131436us
	[DPU avg Time ] 1.36062e+08us
	[DPU avg FPS  ] 7349.57
	
	
	deleting memory buffer
	+ cat ./rpt/log1.txt ./rpt/log2.txt ./rpt/log3.txt
	+ rm -f ./rpt/log1.txt ./rpt/log2.txt ./rpt/log3.txt
	+ echo ' '
	
	+ echo ' IMAGENET RESNET50 PERFORMANCE (fps)'
	 IMAGENET RESNET50 PERFORMANCE (fps)
	+ echo ' '
	
	+ ./get_dpu_fps ./vek280_resnet50_imagenet.xmodel 1 1000
	+ tee ./rpt/log1.txt
	./get_dpu_fps ./vek280_resnet50_imagenet.xmodel 1 1000
	WARNING: Logging before InitGoogleLogging() is written to STDERR
	I20231011 14:43:15.529371 1927228 get_dpu_fps.cc:107] create running for subgraph: subgraph_quant_avg_pool_fix(TransferPoolFixToDwConv2dFix)
	XAIEFAL: INFO: Resource group Avail is created.
	XAIEFAL: INFO: Resource group Static is created.
	XAIEFAL: INFO: Resource group Generic is created.
	outSize   1000
	inSize    150528
	outW      1
	outH      1
	inpW      224
	inpH      224
	inp scale 0.5
	out scale 0.25
	# classes 1000
	batchSize 14
	[average calibration high resolution clock] 0.0807us
	
	
	
	 number of dummy images per thread: 994
	
	 allocated 149624832 bytes for  input buffer
	
	 allocated 994000 bytes for output buffer
	
	
	[DPU tot Time ] 314508us
	[DPU avg Time ] 3.16406e+08us
	[DPU avg FPS  ] 3160.5
	
	
	deleting memory buffer
	+ ./get_dpu_fps ./vek280_resnet50_imagenet.xmodel 2 1000
	+ tee ./rpt/log2.txt
	./get_dpu_fps ./vek280_resnet50_imagenet.xmodel 2 1000
	WARNING: Logging before InitGoogleLogging() is written to STDERR
	I20231011 14:43:17.143707 1927244 get_dpu_fps.cc:107] create running for subgraph: subgraph_quant_avg_pool_fix(TransferPoolFixToDwConv2dFix)
	XAIEFAL: INFO: Resource group Avail is created.
	XAIEFAL: INFO: Resource group Static is created.
	XAIEFAL: INFO: Resource group Generic is created.
	outSize   1000
	inSize    150528
	outW      1
	outH      1
	inpW      224
	inpH      224
	inp scale 0.5
	out scale 0.25
	# classes 1000
	batchSize 14
	[average calibration high resolution clock] 0.06445us
	
	
	
	 number of dummy images per thread: 490
	
	 allocated 147517440 bytes for  input buffer
	
	 allocated 980000 bytes for output buffer
	
	
	[DPU tot Time ] 207249us
	[DPU avg Time ] 2.11478e+08us
	[DPU avg FPS  ] 4728.62
	
	
	deleting memory buffer
	+ tee ./rpt/log3.txt
	+ ./get_dpu_fps ./vek280_resnet50_imagenet.xmodel 3 1000
	./get_dpu_fps ./vek280_resnet50_imagenet.xmodel 3 1000
	WARNING: Logging before InitGoogleLogging() is written to STDERR
	I20231011 14:43:18.662076 1927255 get_dpu_fps.cc:107] create running for subgraph: subgraph_quant_avg_pool_fix(TransferPoolFixToDwConv2dFix)
	XAIEFAL: INFO: Resource group Avail is created.
	XAIEFAL: INFO: Resource group Static is created.
	XAIEFAL: INFO: Resource group Generic is created.
	outSize   1000
	inSize    150528
	outW      1
	outH      1
	inpW      224
	inpH      224
	inp scale 0.5
	out scale 0.25
	# classes 1000
	batchSize 14
	[average calibration high resolution clock] 0.08095us
	
	
	
	 number of dummy images per thread: 322
	
	 allocated 145410048 bytes for  input buffer
	
	 allocated 966000 bytes for output buffer
	
	
	[DPU tot Time ] 204447us
	[DPU avg Time ] 2.11643e+08us
	[DPU avg FPS  ] 4724.94
	
	
	deleting memory buffer
	+ cat ./rpt/log1.txt ./rpt/log2.txt ./rpt/log3.txt
	+ rm -f ./rpt/log1.txt ./rpt/log2.txt ./rpt/log3.txt
	+ echo ' '
	
	PWD4 =  /home/root/target_vek280/imagenet
	
	run resnet18 CNN
	
	WARNING: Logging before InitGoogleLogging() is written to STDERR
	I20231011 14:43:20.056537 1927275 main_resnet50.cc:342] create running for subgraph: subgraph_quant_add
	XAIEFAL: INFO: Resource group Avail is created.
	XAIEFAL: INFO: Resource group Static is created.
	XAIEFAL: INFO: Resource group Generic is created.
	OUT  size 1000
	IN   size 150528
	IN Height 224
	IN Width  224
	batchSize 14
	
	Image : ILSVRC2012_val_00049764.JPEG out_result = 14.5 out index = 409
	top[0] prob = 0.753228  name = analog clock
	top[1] prob = 0.215803  name = wall clock
	top[2] prob = 0.010744  name = bell cote, bell cot
	top[3] prob = 0.008368  name = barometer
	top[4] prob = 0.003953  name = stopwatch, stop watch
	
	Image : ILSVRC2012_val_00049670.JPEG out_result = 7.75 out index = 476
	top[0] prob = 0.271265  name = carousel, carrousel, merry-go-round, roundabout, whirligig
	top[1] prob = 0.060527  name = shoe shop, shoe-shop, shoe store
	top[2] prob = 0.028591  name = skunk, polecat, wood pussy
	top[3] prob = 0.028591  name = night snake, Hypsiglena torquata
	top[4] prob = 0.022267  name = mosquito net
	
	Image : ILSVRC2012_val_00049821.JPEG out_result = 19.25 out index = 547
	top[0] prob = 0.891029  name = electric locomotive
	top[1] prob = 0.044362  name = passenger car, coach, carriage
	top[2] prob = 0.034549  name = bullet train, bullet
	top[3] prob = 0.026907  name = streetcar, tram, tramcar, trolley, trolley car
	top[4] prob = 0.001720  name = freight car
	
	…
	
	Image : ILSVRC2012_val_00049798.JPEG out_result = 11.5 out index = 549
	top[0] prob = 0.310085  name = envelope
	top[1] prob = 0.188076  name = binder, ring-binder
	top[2] prob = 0.146474  name = carton
	top[3] prob = 0.032683  name = wallet, billfold, notecase, pocketbook
	top[4] prob = 0.019823  name = purse
	
	Image : ILSVRC2012_val_00049954.JPEG out_result = 12 out index = 973
	top[0] prob = 0.459629  name = coral reef
	top[1] prob = 0.102557  name = platypus, duckbill, duckbilled platypus, duck-billed platypus, Ornithorhynchus anatinus
	top[2] prob = 0.079872  name = coho, cohoe, coho salmon, blue jack, silver salmon, Oncorhynchus kisutch
	top[3] prob = 0.062204  name = stingray
	top[4] prob = 0.048445  name = eel
	+ TARGET=vek280
	+ echo ' '
	
	+ echo ' IMAGENET RESNET50 TOP1 ACCURACY ON DPU'
	 IMAGENET RESNET50 TOP1 ACCURACY ON DPU
	+ echo ' '
	
	+ python3 ./code_resnet50/src/check_runtime_top1_imagenet.py -i ./rpt/predictions_resnet50_imagenet.log
	+ tee resnet50_result_predictions.log
	./rpt/predictions_resnet50_imagenet.log  has  3510  lines
	number of total images predicted  499
	number of top1 false predictions  151
	number of top1 right predictions  348
	top1 accuracy = 0.70
	+ echo ' '
	
	+ echo ' '
	
	+ echo ' IMAGENET RESNET18 TOP1 ACCURACY ON DPU'
	 IMAGENET RESNET18 TOP1 ACCURACY ON DPU
	+ echo ' '
	
	+ python3 ./code_resnet50/src/check_runtime_top1_imagenet.py -i ./rpt/predictions_resnet18_imagenet.log
	+ tee resnet18_result_predictions.log
	./rpt/predictions_resnet18_imagenet.log  has  3510  lines
	number of total images predicted  499
	number of top1 false predictions  203
	number of top1 right predictions  296
	top1 accuracy = 0.59
	+ echo ' '
	
	+ echo ' '
	
	+ echo ' IMAGENET RESNET18 PERFORMANCE (fps)'
	 IMAGENET RESNET18 PERFORMANCE (fps)
	+ echo ' '
	
	+ ./get_dpu_fps ./vek280_resnet18_imagenet.xmodel 1 1000
	+ tee ./rpt/log1.txt
	./get_dpu_fps ./vek280_resnet18_imagenet.xmodel 1 1000
	WARNING: Logging before InitGoogleLogging() is written to STDERR
	I20231011 14:43:28.414808 1927331 get_dpu_fps.cc:107] create running for subgraph: subgraph_quant_add
	XAIEFAL: INFO: Resource group Avail is created.
	XAIEFAL: INFO: Resource group Static is created.
	XAIEFAL: INFO: Resource group Generic is created.
	outSize   1000
	inSize    150528
	outW      1
	outH      1
	inpW      224
	inpH      224
	inp scale 0.25
	out scale 0.25
	# classes 1000
	batchSize 14
	[average calibration high resolution clock] 0.0807us
	
	
	
	 number of dummy images per thread: 994
	
	 allocated 149624832 bytes for  input buffer
	
	 allocated 994000 bytes for output buffer
	
	
	[DPU tot Time ] 240883us
	[DPU avg Time ] 2.42337e+08us
	[DPU avg FPS  ] 4126.49
	
	
	deleting memory buffer
	+ ./get_dpu_fps ./vek280_resnet18_imagenet.xmodel 2 1000
	+ tee ./rpt/log2.txt
	./get_dpu_fps ./vek280_resnet18_imagenet.xmodel 2 1000
	WARNING: Logging before InitGoogleLogging() is written to STDERR
	I20231011 14:43:29.512655 1927341 get_dpu_fps.cc:107] create running for subgraph: subgraph_quant_add
	XAIEFAL: INFO: Resource group Avail is created.
	XAIEFAL: INFO: Resource group Static is created.
	XAIEFAL: INFO: Resource group Generic is created.
	outSize   1000
	inSize    150528
	outW      1
	outH      1
	inpW      224
	inpH      224
	inp scale 0.25
	out scale 0.25
	# classes 1000
	batchSize 14
	[average calibration high resolution clock] 0.0603us
	
	
	
	 number of dummy images per thread: 490
	
	 allocated 147517440 bytes for  input buffer
	
	 allocated 980000 bytes for output buffer
	
	
	[DPU tot Time ] 133163us
	[DPU avg Time ] 1.35881e+08us
	[DPU avg FPS  ] 7359.41
	
	
	deleting memory buffer
	+ ./get_dpu_fps ./vek280_resnet18_imagenet.xmodel 3 1000
	+ tee ./rpt/log3.txt
	./get_dpu_fps ./vek280_resnet18_imagenet.xmodel 3 1000
	WARNING: Logging before InitGoogleLogging() is written to STDERR
	I20231011 14:43:30.520401 1927352 get_dpu_fps.cc:107] create running for subgraph: subgraph_quant_add
	XAIEFAL: INFO: Resource group Avail is created.
	XAIEFAL: INFO: Resource group Static is created.
	XAIEFAL: INFO: Resource group Generic is created.
	outSize   1000
	inSize    150528
	outW      1
	outH      1
	inpW      224
	inpH      224
	inp scale 0.25
	out scale 0.25
	# classes 1000
	batchSize 14
	[average calibration high resolution clock] 0.06305us
	
	
	
	 number of dummy images per thread: 322
	
	 allocated 145410048 bytes for  input buffer
	
	 allocated 966000 bytes for output buffer
	
	
	[DPU tot Time ] 132584us
	[DPU avg Time ] 1.37251e+08us
	[DPU avg FPS  ] 7285.94
	
	
	deleting memory buffer
	+ cat ./rpt/log1.txt ./rpt/log2.txt ./rpt/log3.txt
	+ rm -f ./rpt/log1.txt ./rpt/log2.txt ./rpt/log3.txt
	+ echo ' '
	
	+ echo ' IMAGENET RESNET50 PERFORMANCE (fps)'
	 IMAGENET RESNET50 PERFORMANCE (fps)
	+ echo ' '
	
	+ ./get_dpu_fps ./vek280_resnet50_imagenet.xmodel 1 1000
	+ tee ./rpt/log1.txt
	./get_dpu_fps ./vek280_resnet50_imagenet.xmodel 1 1000
	WARNING: Logging before InitGoogleLogging() is written to STDERR
	I20231011 14:43:31.591747 1927366 get_dpu_fps.cc:107] create running for subgraph: subgraph_quant_avg_pool_fix(TransferPoolFixToDwConv2dFix)
	XAIEFAL: INFO: Resource group Avail is created.
	XAIEFAL: INFO: Resource group Static is created.
	XAIEFAL: INFO: Resource group Generic is created.
	outSize   1000
	inSize    150528
	outW      1
	outH      1
	inpW      224
	inpH      224
	inp scale 0.5
	out scale 0.25
	# classes 1000
	batchSize 14
	[average calibration high resolution clock] 0.0766us
	
	
	
	 number of dummy images per thread: 994
	
	 allocated 149624832 bytes for  input buffer
	
	 allocated 994000 bytes for output buffer
	
	
	[DPU tot Time ] 315518us
	[DPU avg Time ] 3.17423e+08us
	[DPU avg FPS  ] 3150.37
	
	
	deleting memory buffer
	+ tee ./rpt/log2.txt
	+ ./get_dpu_fps ./vek280_resnet50_imagenet.xmodel 2 1000
	./get_dpu_fps ./vek280_resnet50_imagenet.xmodel 2 1000
	WARNING: Logging before InitGoogleLogging() is written to STDERR
	I20231011 14:43:33.182615 1927382 get_dpu_fps.cc:107] create running for subgraph: subgraph_quant_avg_pool_fix(TransferPoolFixToDwConv2dFix)
	XAIEFAL: INFO: Resource group Avail is created.
	XAIEFAL: INFO: Resource group Static is created.
	XAIEFAL: INFO: Resource group Generic is created.
	outSize   1000
	inSize    150528
	outW      1
	outH      1
	inpW      224
	inpH      224
	inp scale 0.5
	out scale 0.25
	# classes 1000
	batchSize 14
	[average calibration high resolution clock] 0.0807us
	
	
	
	 number of dummy images per thread: 490
	
	 allocated 147517440 bytes for  input buffer
	
	 allocated 980000 bytes for output buffer
	
	
	[DPU tot Time ] 207362us
	[DPU avg Time ] 2.11594e+08us
	[DPU avg FPS  ] 4726.03
	
	
	deleting memory buffer
	+ ./get_dpu_fps ./vek280_resnet50_imagenet.xmodel 3 1000
	+ tee ./rpt/log3.txt
	./get_dpu_fps ./vek280_resnet50_imagenet.xmodel 3 1000
	WARNING: Logging before InitGoogleLogging() is written to STDERR
	I20231011 14:43:34.699926 1927393 get_dpu_fps.cc:107] create running for subgraph: subgraph_quant_avg_pool_fix(TransferPoolFixToDwConv2dFix)
	XAIEFAL: INFO: Resource group Avail is created.
	XAIEFAL: INFO: Resource group Static is created.
	XAIEFAL: INFO: Resource group Generic is created.
	outSize   1000
	inSize    150528
	outW      1
	outH      1
	inpW      224
	inpH      224
	inp scale 0.5
	out scale 0.25
	# classes 1000
	batchSize 14
	[average calibration high resolution clock] 0.0815us
	
	
	
	 number of dummy images per thread: 322
	
	 allocated 145410048 bytes for  input buffer
	
	 allocated 966000 bytes for output buffer
	
	
	[DPU tot Time ] 204596us
	[DPU avg Time ] 2.11797e+08us
	[DPU avg FPS  ] 4721.49
	
	
	deleting memory buffer

	PWD4 =  /home/root/target_vek280/imagenet

target/cifar10/run_all_cifar10_target.sh/end_cif10()

#remove images
end_cif10(){
echo " "
echo "end of cifar10"
echo " "
cd cifar10
rm -rf test
cd ../
echo "PWD5 = " $PWD
#tar -cvf target.tar ./target_*
}
	end of imagenet
	
	PWD5 =  /home/root/target_vek280
	root@xilinx-vek280-es1-20231:~/target_vek280# 	
profile
공기정

0개의 댓글

관련 채용 정보