히트맵 생성 가속화 시행착오

0~255를 취하는 값으로부터 히트 맵(RGB)을 산출하는 프로그램을 만들고 있었습니다만,
처음 쓴 소스(GPU+Cupy)가 너무 느려서 시행착오한 결과를 남깁니다.

※cv2.applyColorMap(grayscale_image,cv2.COLORMAP_JET)로 모두 해결이었습니다만, 자작해 버렸습니다(부끄러움).

다음은 이미지 크기 320x180에 대한 처리입니다.
코드는 주요 부분만 싣고 있습니다.
또, 히트 맵은 근사치를 구하는 간이판(삼각 함수 미사용)입니다
( 값의 크기를 서모그래피와 같은 색으로 변환 선형 그림).


GPU+Cupy(for)



원래 쓴 코드입니다.
어리석게 for로 돌려 처리하는 패배 코드 입니다.
    def conv_v_to_heat(v):
        image = cuda.cupy.zeros((v.shape[0], array.v[1], 4))
        for i, w in enumerate(image):
            for j, h in enumerate(w):
                image[i,j,0] = get_heat_r(array[i][j])
                image[i,j,1] = get_heat_g(array[i][j])
                image[i,j,2] = get_heat_b(array[i][j])
                image[i,j,3] = array[i][j] # アルファは適当

    def get_heat_r(v):
        if v <= 127:
            return 0
        elif v <= 190:
            return (v-127)*4
        else:
            return 255
sec: 20.43495798110962

CPU+Numpy(for)



for 사용하는 정도라면 GPU 그만두는 편이 아직 괜찮은 것은?
라고 생각해 CPU로 바꾸었습니다(소스 생략).bash
sec: 0.6369609832763672
CPU 쪽이 전혀 빨랐습니다.

CPU+Numba+Numpy(for)



Numba 넣어 보았습니다.
    @jit
    def conv_v_to_heat(v):

    @jit
    def get_heat_r(v):
sec: 0.20061397552490234

더욱 빨라졌습니다.

CPU+Numba+Numpy(filter)



원래, Numpy에 for를 사용할 때 패배이므로,
필터링으로 대처하도록 했습니다.
    def conv_v_to_heat(v):
       image = np.zeros((v.shape[0], v.shape[1], 4))
        image[:, :, 0] = get_r(array)
        image[:, :, 1] = get_g(array)
        image[:, :, 2] = get_b(array)
        image[:, :, 3] = v

    def get_heat_r(v):
        out = np.zeros((v.shape))
        out[...] = 255
        out[(v<=190)] = (v[(v<=190)]-127)*4
        out[(v<=127)] = 0
        return out
sec: 0.0013210773468017578

압도적으로 빨라졌습니다.

CPU+Numpy(filter)



시도해 보면 Numba를 제거해 보겠습니다.
sec: 0.001230478286743164

그건 빨라졌습니다. 라고 할까 오차 레벨입니다.

GPU+Cupy(filter)



그럼 GPU는?
sec: 0.008527278900146484

늦어졌습니다.

요약




구현
time(sec)


GPU+Cupy(for)
20.43495798110962

CPU+Numpy(for)
0.63696098327637

CPU+Numba+Numpy(for)
0.20061397552490

CPU+Numba+Numpy(filter)
0.00132107734680

CPU+Numpy(filter)
0.00123047828674

GPU+Cupy(filter)
0.00852727890015


CPU+Numpy(filter)가 제일이었습니다.
보다 빠른 구현은 있다고 생각합니다만, 개인적으로는 만족 가는 속도가 되었습니다.
역시, for 사용하면 지는군요.

좋은 웹페이지 즐겨찾기