카테고리 보관물: Personal projects

CARLA client를 build해야 하는데 clang-8이 없댄다.

2022년 9월 현재 CARLA simulator의 최신 버전인 0.9.13으로 PythonAPI를 빌드하려고 하면 clang-8 version을 요구하는데 Ubuntu 22.04에서는 clang-8의 repository를 추가하고 설치 시도하면 다음과 같이 의존성 오류가 생긴다.

The following packages have unmet dependencies:
 clang-8 : Depends: libllvm8 (>= 1:8~svn298832-1~) but it is not going to be installed
           Depends: libstdc++-5-dev but it is not installable
           Depends: libgcc-5-dev but it is not installable
           Depends: libobjc-5-dev but it is not installable
           Depends: libclang-common-8-dev (= 1:8.0.1+svn369350-1~exp1~20200112113617.82) but it is not going to be installed
           Depends: libclang1-8 (= 1:8.0.1+svn369350-1~exp1~20200112113617.82) but it is not going to be installed
           Recommends: llvm-8-dev but it is not going to be installed
           Recommends: libomp-8-dev but it is not going to be installed
 lld-8 : Depends: libllvm8 (= 1:8.0.1+svn369350-1~exp1~20200112113617.82) but it is not going to be installed
E: Unable to correct problems, you have held broken packages.

그리고 아쉽게도 하위 호환에 문제가 있는 것인지 설치 가능한 최하 버전인 clang-10으로는 CARLA client build가 되지 않는다. 빌드 스크립트에서 버전 점검하는 부분을 건너 뛰도록 수정하고 clang-10으로 강제 빌드를 시도해봤더니 역시나 빌드오류가 나면서 일이 커질것 같다는 느낌이 강하게 든다.

일일이 빌드오류 잡는 삽질을 하고 ‘CARLA client build 삽질기’를 포스팅 할 수도 있었겠지만 이번에는 문명의 이기인 Docker를 한번 누려 보기로했다.

먼저, Docker로 clang-8 설치가 가능한 Ubuntu 18.04에서 빌드를 수행한 다음(참고 CARLA – Linux Build) 빌드가 완료되면 Python client package를 host에 설치한다.

  • Docker로 Ubuntu18.04를 설치하고 CARLA의 소스 코드위치를 /carla로 마운트하여 실행한다.
$ docker pull ubuntu:18.04
$ docker run -ti -v <carla-root-path>:/carla ubuntu:18.04 /bin/bash
  • Clang-8의 repository를 추가하고 관련된 패키지들을 설치한다.
# Clang-8 repository 추가.
DOCKER# apt-get update &&
apt-get install wget software-properties-common &&
add-apt-repository ppa:ubuntu-toolchain-r/test &&
wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key|apt-key add - &&
apt-add-repository "deb http://apt.llvm.org/xenial/ llvm-toolchain-xenial-8 main" &&
apt-get update

# Install packages.
DOCKER# apt-get install -y build-essential clang-8 lld-8 g++-7 cmake ninja-build libvulkan1 python python-pip python-dev python3-dev python3-pip libpng-dev libtiff5-dev libjpeg-dev tzdata sed curl unzip autoconf libtool rsync libxml2-dev git
  • Clang-8을 default로 설정한다.
# Set clang-8 as a default clang.
DOCKER# update-alternatives --install /usr/bin/clang++ clang++ /usr/lib/llvm-8/bin/clang++ 180 && update-alternatives --install /usr/bin/clang clang /usr/lib/llvm-8/bin/clang 180
  • Host machine의 python과 동일한 버전(3.8)을 docker에도 설치하고 관련된 Python package들을 pip로 설치해준다. 특별히 setuptools package는 버전의 영향을 받으므로 확인된 버전(47.3.1)을 명시해 준다.
DOCKER# apt install -y python3.8 python3.8-dev

# PIP upgrade
DOCKER# pip3 install --upgrade pip && pip install --upgrade pip

# 중요. Python3의 setuptools version이 안맞으면 빌드에 실패할 수 있으니 버전명을 명시해 준다.
DOCKER# pip2 install setuptools &&
pip3 install -Iv setuptools==47.3.1 &&
pip2 install distro &&
pip3 install distro &&
pip2 install wheel &&
pip3 install wheel auditwheel
  • 이제 해당 버전으로 docker에서 build를 시도 한다.
DOCKER# cd /carla
DOCKER# make PythonAPI ARGS="--python-version=3.8"
  • /carla/PythonAPI/carla/dist 아래에 소스에 포함되어 있는 3.6용 package외에 새롭게 빌드한 3.8용 *.whl, *.egg file들이 생성된 것을 확인하고 host system에 설치해 준다.
DOCKER# ls /carla/PythonAPI/carla/dist/
carla-0.9.13-cp36-cp36m-linux_x86_64.whl  carla-0.9.13-py3.6-linux-x86_64.egg
carla-0.9.13-cp38-cp38m-linux_x86_64.whl  carla-0.9.13-py3.8-linux-x86_64.egg

# CARLA client 설치
$ sudo apt install -y <carla-root-path>/PythonAPI/carla/dist/carla-0.9.13-py3.8-linux-x86_64.egg

Android recovery image 빌드 설정

1. BoardConfig.mk 수정
TARGET_NO_KERNEL과 TARGET_NO_RECOVERY가 true로 설정되어 있다면 설정한다.

2. device.mk 수정
TARGET_PREBUILT_KERNEL관련 설정을 삭제한다.

3. AndroidBoard.mk 추가
Kernel build 될 때 참고되는 파일이므로 추가해 주고 KERNEL_DEFCONFIG등의 설정을 자신에 맞게 변경해 준다.

4. AndroidKernel.mk 추가
AndroidKernel.mk는 kernel build를 위한 makefile script이다.

5. defconfig file 경로변경
defconfig file이 참조될 수 있도록 kernel/$(ARCH)/configs 아래에 옮겨준다.

6. 상대경로 참조로 인한 compile error 수정
Android build에 포함된 kernel build는 상대 경로를 참조하는 경우 build error를 발생할 수 있다. 절대 경로 path를 주기 위해 절대 경로를 얻고 make command line에 이를 넘겨주는 부분을 추가해 준다.

OpenVINO python을 이용한 inferencing 예제

OpenVINO를 이용해서 TensorFlow(Keras)로 training한 모델로 추론(inferencing)을 수행하는 간단한 예제를 작성해 보았다.

TensorFlow model을 freeze하기

Training된 모델을 model optimizer에 넣기 전에 freeze시켜야 하는데, output_node_names를 입력하라는 오류 메세지가 계속 뜬다면 제대로 freezing을 수행했는지 확인해 보는게 좋다. 알아보기 쉽게 하기 위해 입출력 layer에 ‘name=’ parameter로 다음과 같이 이름을 지정해 주었다.

model = tf.keras.models.Sequential([
    tf.keras.layers.Flatten(input_shape=(28, 28), name='input'),
    tf.keras.layers.Dense(128, activation='relu'),
    tf.keras.layers.Dropout(0.2),
    tf.keras.layers.Dense(10, activation='softmax', name='output')
])

그러면 layer의 이름들을 출력할 때 다음과 같이 나온다. 전체 MINST model training과 freezing 과정은 이 CoLab에 적어 두었으니 참조.

------------------------------------------------------------
Frozen model layers:
x
sequential/input/Const
sequential/input/Reshape
sequential/dense/MatMul/ReadVariableOp/resource
sequential/dense/MatMul/ReadVariableOp
sequential/dense/MatMul
sequential/dense/BiasAdd/ReadVariableOp/resource
sequential/dense/BiasAdd/ReadVariableOp
sequential/dense/BiasAdd
sequential/dense/Relu
sequential/dropout/Identity
sequential/output/MatMul/ReadVariableOp/resource
sequential/output/MatMul/ReadVariableOp
sequential/output/MatMul
sequential/output/BiasAdd/ReadVariableOp/resource
sequential/output/BiasAdd/ReadVariableOp
sequential/output/BiasAdd
sequential/output/Softmax
Identity
------------------------------------------------------------

모델 옵티마이저(mo-tf.py)

Freeze된 모델을 다운로드 받은 후에 TensorFlow용 model optimizer인 mo-tf.py를 실행 시키면 model을 나타내는 xml file과 weight값을 저장하는 bin file이 생성된다. 이 때 training된 모델은 입력 shape을 [-1, 28, 28]로 알고 있기 때문에 음수가 아닌 값을 넣어 달라는 에러가 생긴다. –input_shape parameter를 다음과 같이 적어준다.

/opt/intel/openvino_2021/deployment_tools/model_optimizer/mo_tf.py --input_model ./model/mnist_model/frozen_graph.pb  --input_shape [28,28]

OpenVINO를 이용한 inferencing

Model optimizer가 수행되었다면 이제 xml file을 이용해 model을 load하고 inferencing을 수행하면 된다. 다음은 Training 후 freezing과 model optimization이 수행된 XML file을 이용해서 inferencing을 수행하는 간단한 코드이다.

출력결과

$ python3 ./infer_mnist.py ./model/mnist_model/frozen/frozen_graph.xml

        Model path= ./model/mnist_model/frozen/frozen_graph.xml 
        Device= CPU
Accuracy: 0.9789 (hit: 9789/ miss: 211)

stb library를 이용한 간단한 이미지 읽고 쓰기

stb는 라이센스 걱정없이 사용할 수 있는 간단한 이미지 읽고 쓰기, 폰트, vorbis등에 대한 퍼블릭 도메인 구현으로 간단한 이미지 처리 등을 지원하기 위해 임베디드 시스템 등에서 고려해 볼만 하다. 다음은 테스트용 이미지(아무 포맷)를 읽어서 BMP로 저장하는 예제이다.

XCode에서 OpenCL 개발환경 설정과 간단한 디바이스 정보 출력 예제

  1. XCode에서 새로운 프로젝트를 생성하고 macOS의 Command Line Tool을 선택한다.
  2. Project를 선택하고 ‘Build Phases’ -> ‘Link Binary With Libraries’에서 더하기(+)를 선택한 후 OpenCL framework을 선택한다.

아래의 예제 코드는 OpenCL programming by example의 2장에 나오는 내용을 약간 변경한 것으로 AMD 라데온 Pro 455와 Intel HD graphics 530두 개의 GPU가 달린 2016년 맥북프로에서 실행하면 다음과 같은 결과가 출력된다.

Number of platforms: 1
3 devices found in platform0
	Name: Intel(R) Core(TM) i7-6820HQ CPU @ 2.70GHz
	Type: 2
	Image support: 1
	Vendor: Intel
	Driver ver.: 1.1
	Device ver.: OpenCL 1.2 
	Compute units: 8
	Max clock: 2700 MHz
		Denorms: 1
		INF and quiet NaNs: 1
		Round to nearest: 1
		Round to zero: 1
		Round to INF: 1
		FMA: 1

	Name: Intel(R) HD Graphics 530
	Type: 4
	Image support: 1
	Vendor: Intel Inc.
	Driver ver.: 1.2(Aug 31 2020 22:26:30)
	Device ver.: OpenCL 1.2 
	Compute units: 24
	Max clock: 1050 MHz
		Denorms: 1
		INF and quiet NaNs: 1
		Round to nearest: 1
		Round to zero: 1
		Round to INF: 1
		FMA: 1

	Name: AMD Radeon Pro 455 Compute Engine
	Type: 4
	Image support: 1
	Vendor: AMD
	Driver ver.: 1.2 (Sep 11 2020 22:04:49)
	Device ver.: OpenCL 1.2 
	Compute units: 12
	Max clock: 855 MHz
		Denorms: 1
		INF and quiet NaNs: 1
		Round to nearest: 1
		Round to zero: 1
		Round to INF: 1
		FMA: 1

Program ended with exit code: 0