2022년 1월 7일 금요일

Folding(Fusing) Batch normalization

1. Batch normalization


$\gamma,\beta$는 학습중에 지속적으로 업데이트되는 trainable한 변수입니다.
$\mu,\sigma$은 mini batch에서 계산되는 평균값과 표준편차값입니다.
$\mu_{avg}, \sigma_{avg}$은 inference과정에서 사용하기위해 moving average로 축적하는 값입니다.






2. Folding(Fusing) batch normalization

<inception block>

일반적으로 위와 같이 convolution layer와 batch normalization, 그리고 activation function을 연달아 사용하는 
block형태로 일반화되어 사용하는데 Folding(Fusing) batch normalization은 convolution layer와 batch normalization layer가 
결합되어 최적화를 한 layer를 말합니다.


$1.$   $y_{conv}=Wx+b$
-  convolution layer는 위의 식으로 표현됩니다.

$2.$   $\hat{x}=\frac{x-\mu}{\sqrt{\sigma^{2}+\epsilon}}$
$3.$   $y=\gamma\hat{x}+\beta$
-  batch normalization layer는 위의 식으로 표현됩니다.

$4.$   $y=\frac{\gamma(x-\mu)}{\sqrt{\sigma^{2}+\epsilon}}+\beta$                     $\because(2.\cup3.)$
$5.$   $y=\frac{\gamma(Wx+b-\mu)}{\sqrt{\sigma^{2}+\epsilon}}+\beta$                     $\because(1.\cup4.)$
-  batch normalization layer의 input이 convolution layer의 output이 되기 때문에 두 과정을 결합할 수 있습니다.
 
$6.$   $y=\frac{\gamma W}{\sqrt{\sigma^{2}+\epsilon}}x+\gamma\frac{b-\mu}{\sqrt{\sigma^{2}+\epsilon}}+\beta$     $\approx$    $y_{inference}=\frac{\gamma W}{\sqrt{\sigma_{avg}^{2}+\epsilon}}x_{inference}+\gamma\frac{b-\mu_{avg}}{\sqrt{\sigma_{avg}^{2}+\epsilon}}+\beta$      $\approx$    $y_{inference}=\dot{W}x_{inference}$ $+\dot{b}$
-  결국 최종형태의 식은 $y=\dot{W}x$ $+\dot{b}$형태가 되는데 inference과정에서의 $\dot{W}, \dot{b}$값은 모두 상수이기 때문에
   시간복잡도 $O(1)$로 굉장히 빨리 계산할 수 있게됩니다.





3. Tensorflow code
tensorflow2.7버젼 기준으로 batch normalization은 위의 API로 정의 되어있습니다.
앞서 설명한 fusing관련된 argument가 없어보이지만 실제로는 내부적으로 wrapping 돼 있어 
fused = False # or True
와 같이 argument를 추가적으로 명시해줄 수 있습니다.


fused의 코드들을 쭉 따라가다보면  아래와 같은 코드를 볼 수 있게되는데 (https://github.com/tensorflow/tensorflow/blob/v2.7.0/tensorflow/python/ops/nn_impl.py#L1586-L1691)
@tf_export("nn.batch_normalization")
@dispatch.add_dispatch_support
def batch_normalization(x,
                        mean,
                        variance,
                        offset,
                        scale,
                        variance_epsilon,
                        name=None):
  ...
  ...
  y, running_mean, running_var, _, _, _ = gen_nn_ops.fused_batch_norm_v3(
      x,
      scale,
      offset,
      mean,
      variance,
      epsilon=epsilon,
      exponential_avg_factor=exponential_avg_factor,
      data_format=data_format,
      is_training=is_training,
      name=name)
  return y, running_mean, running_var
더이상 fused_batch_norm_v3를 실행하는 gen_nn_ops라는 라이브러리를 따라갈 수 없게됩니다.
그 이유는 bazel빌드를 통해서 만들어지는 파일이기 때문입니다.

실제 코드는 C++로 구현이 되어있으며 gen_nn_ops는 단순히 python으로 wrapping되어있는것 뿐인것이죠.


fused_batch_norm API의 자세한 C++코드를 보고 싶으다면 아래의 링크에서 확인할 수 있습니다.





[Reference]

2022년 1월 3일 월요일

OpenCL - WSL2에 OpenCL 설치하기

OpenCL

OpenCL(Open Computing Language)은 병렬 처리를 위한 표준 API(Application Programming Interface)입니다.
CPU, GPU, FPGA 등 다양한 병렬 처리 장치에서 작업을 병렬화하여 처리할 수 있도록 지원합니다.

OpenCL은 C99 언어를 기반으로 하며, 프로그래머가 병렬 처리를 위한 코드를 작성하면 OpenCL 런타임이 자동으로 해당 코드를 여러 개의 작은 작업으로 분할하여 병렬 처리 장치에 할당합니다.

OpenCL은 다음과 같은 기능을 제공합니다.

  • 하드웨어 추상화
  • 자동 병렬화
  • 동적 디바이스 및 커널 선택
  • 메모리 관리 및 전송
  • 프로그램 빌드 및 컴파일


회사에서는 주로 ubuntu를 사용하다 보니 제 PC는 WSL2로 ubuntu 환경을 구축 해놓았습니다.
WSL2 환경에 OpenCL을 설치하는 방법을 알아보도록 하겠습니다.


WSL2에서 OpenCL 설치하기

먼저 제 PC환경은 아래와 같습니다.

  • OS: Windows 11
  • WSL2: Ubuntu 20.04
  • CPU: Intel i7
  • GPU: Intel(R) Iris(R) XE Graphics


1. OpenCL package 다운로드

$ mkdir neo
$ cd neo
$ wget https://github.com/intel/intel-graphics-compiler/releases/download/igc-1.0.12149.1/intel-igc-core_1.0.12149.1_amd64.deb
$ wget https://github.com/intel/intel-graphics-compiler/releases/download/igc-1.0.12149.1/intel-igc-opencl_1.0.12149.1_amd64.deb
$ wget https://github.com/intel/compute-runtime/releases/download/22.39.24347/intel-level-zero-gpu-dbgsym_1.3.24347_amd64.ddeb
$ wget https://github.com/intel/compute-runtime/releases/download/22.39.24347/intel-level-zero-gpu_1.3.24347_amd64.deb
$ wget https://github.com/intel/compute-runtime/releases/download/22.39.24347/intel-opencl-icd-dbgsym_22.39.24347_amd64.ddeb
$ wget https://github.com/intel/compute-runtime/releases/download/22.39.24347/intel-opencl-icd_22.39.24347_amd64.deb
$ wget https://github.com/intel/compute-runtime/releases/download/22.39.24347/libigdgmm12_22.2.0_amd64.deb
cs


2. OpenCL package 설치

$ sudo apt install ./*.deb
$ sudo apt install -y clinfo
cs


3. OpenCL 패키지 설치 확인

/usr/bin/clinfo -l

Platform #0: Intel(R) OpenCL HD Graphics
 `-- Device #0: Intel(R) Graphics [0x9a49]
cs

 

4. NEO 드라이버, OpenCL 라이브러리 설치

$ sudo add-apt-repository ppa:intel-opencl/intel-opencl
$ sudo apt-get update
$ sudo apt install intel-opencl-icd
 
$ sudo apt-get update
$ sudo apt-get install ocl-icd-opencl-dev
cs


5. OpenCL 라이브러리 확인

$ ls /usr/lib/x86_64-linux-gnu | grep CL
libOpenCL.so
libOpenCL.so.1
libOpenCL.so.1.0.0
cs


Reference: