<밑바닥부터 시작하는 딥러닝2>의 4장과 6장에서 cupy를 사용할 수 있는데,
CPU만으로 훈련시키자면 오랜 시간이 걸린다. 그래서 GPU 옵션(cupy)를 켜고 실행하면 에러가 바로 난다.
(필자는 i7 10700k, 16G RAM, RTX 3060 12GB GPU 를 메인시스템으로, i7 3770, 22G RAM, 저렴한 라데온 그래픽카드를 서브 시스템으로 사용하고 있다. 물론 RTX 3060 같은 Nvidia 그래픽 카드를 제대로 설치하고, cupy도 설치하고 난 후의 경우다.)
AttributeError: module 'cupy' has no attribute 'scatter_add'
common/np.py 를 열어보면,
np.add.at = np.scatter_add
이 있는데
# np.add.at = np.scatter_add
이렇게 주석처리한다.
GPU로 설정되면 위 코드가 실행되는데,
cupy에 scatter_add라는 함수가 예전 버전에는 있었는데 최근 들어서는 제거되고 cupyx에 들어갔다고 한다.
<밑바닥 딥러닝> 소스코드 메인 폴더에서 해당 문구를 검색을 해보자.
$ cat `find . | grep ".py"` | grep scatter_add
np.add.at = np.scatter_add
딱 한군데에서 scatter_add를 사용하고 있다. 역시 np.add.at을 검색해보면,
$ cat `find . | grep ".py"` | grep "np.add.at"
np.add.at = np.scatter_add
np.add.at(dW, self.idx, dout)
딱 두 군데에서 np.add.at을 언급하고 있다.
요약:
cupy에 np.add.at 이 없음. scatter_add 는 예전 버전에는 있었는데 현재 버전에서는 제거되었음.
cupyx에 넘파이의 np.add.at에 호환되는 scatter_add 함수 있음.
numpy에 np.add.at은 cupyx에 scatter_add 함수와 호환됨.
따라서 처리 방법은, common/ 폴더 안에 있는 두 파일의 코드를 살짝 수정한다. 위에서도 언급했지만,
1) np.py의
np.add.at = np.scatter_add
주석 처리.
2) layers.py 의 166번째 줄. (class Embedding: 부분)
np.add.at(dW, self.idx, dout)
이 라인을 다음과 같이 수정한다.
if GPU:
import cupyx
cupyx.scatter_add(dW, self.idx, dout)
else:
np.add.at(dW, self.idx, dout)
cupyx 모듈은 위 함수 호출에서 딱 한번만 실행되고 실행 결과를 괄호 안의 변수들에 저장시켜주고 끝나기 때문에 전체 cupy 처리에는 아무런 지장을 주지 않는다.