[jupyter] notebook for C++

spring·2020년 11월 9일
1

1. Jupyter 설치하기

Jupyter 는 Python3 으로 설치하길 권장하고 있다.

apt update && apt install python3-pip -y
pip3 install --upgrade pip
pip3 install jupyter

2. Apache2 SSL 설치

apt install apache2
a2enmod ssl
mkdir /etc/apache2/ssl
openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/apache2/ssl/apache.key -out /etc/apache2/ssl/apache.crt
vim /etc/apache2/sites-available/default-ssl.conf

아래 두 설정을 위에서 만든 crt와 key로 설정한다.

<VirtualHost *:443>
    ServerAdmin webmaster@localhost
    #DocumentRoot /var/www/html

    .
    .
    .

    SSLCertificateFile      /etc/apache2/ssl/apache.crt
    SSLCertificateKeyFile /etc/apache2/ssl/apache.key
    
    .
    .
    .

</VirtualHost>
a2ensite default-ssl
service apache2 restart

이제 /var/www/html/index.html 에서 아래의 코드로 Jupyter 쪽 포트를 연결해 리다이렉트 시키면 된다.

3. Jupyter 를 원격 서버로 설정하기

jupyter notebook --generate-config

만약 에러가 뜬다면 아래의 패키지를 설치한다.

apt install jupyter-core jupyter-notebook

/root/.jupyter/ 폴더 안에 생성 된다.

python을 실행한뒤 아래의 코드를 입력하면 sha1 값이 뜨는데 그 값을 저장해두자.

In [1]: from notebook.auth import passwd
In [2]: passwd()
Enter password: 
Verify password: 
Out[2]: 'sha1:thisisexamplesha1pleasecopythisvaluetoanywheregoodluck'

SSL을 설정은 아까 위에서 생성한 apache.key 와 apache.crt 를 사용하면 된다.

이제 jupyter_notebook_config.py 를 열어서 아래의 내용을 추가한다. 그냥 첫줄에 추가하면 된다. 이 파일은 모두 주석이다.

c.NotebookApp.allow_origin = '*'
c.NotebookApp.base_url = u'/jupyter'
c.NotebookApp.certfile = u'/root/.jupyter/apache.crt'
c.NotebookApp.ip = '당신의 아이피'
c.NotebookApp.keyfile = u'/root/.jupyter/apache.key'
c.NotebookApp.open_browser = False
c.NotebookApp.password = u'sha1:thisisexamplesha1pleasecopythisvaluetoanywheregoodluck'
c.NotebookApp.trust_xheaders = True
c.NotebookApp.notebook_dir = '주피터의 실행 디렉터리'

4. xeus-cling 설치하기

일반 cling은 이미지를 띄울 방법이 없다. python 은 pyplot을 통해 이미지를 출력하지만 C++ 은 방법이 없으므로 , 그러한 기능이 있는 xeus-cling을 설치해야 한다.

https://conda.io/miniconda.html 이 사이트에서 다운로드 할 수 있고, 서버는 웹 브라우저를 열 수 없으니 아래의 명령으로 받아서 설치하면 된다.
conda는 python2.7 용으로 받는다. 기존의 python3 이 업그레이드되어 망가지기 때문이다.

curl -L https://repo.continuum.io/miniconda/Miniconda2-latest-Linux-x86_64.sh -o conda.sh
sh conda.sh

그 후에는 아래의 명령어들로 쭉 설치하면 된다. 중간에 .bashrc에 추가할까요? 라고 물어보는데 기본값이 no 이므로 만일 no를 했으면 중간에 출력하는 경로를 .bashrc 마지막에 추가하면 된다.

cd ~
source .bashrc
conda create -n cling
source activate cling
conda install cling -c QuantStack -c conda-forge
conda install xeus-cling -c QuantStack -c conda-forge
conda install notebook -c conda-forge

.bashr에 아래 path추가

PATH=$PATH:/home/spring/miniconda2/envs/cling/bin

cling이 적용된 jupyter를 실행하려면 아래와 같이 한다.

source activate cling
jupyter notebook

5. printf,puts,putc

xeus-cling은 C++용인데, C API가 동작하긴 하나, printf와 같은 출력문은 동작하지 않는다.

따라서 C++ io api만 사용하면 된다. 표준IO 헤더를 수정하면 실행되지 않는다.

6. 라이브러리 패스 등록

기본적으로 /usr/lib을 사용하는 것 같다.
g++과 분리를 위해 ~/miniconda2/envs/cling/share/jupyter/kernels/xcpp14 에서
kernel.json 파일을 열어 아래와 같이 라이브러리 패스를 추가해 준다.

{
  "display_name": "C++14",
  "argv": [
      "/home/spring/miniconda2/envs/cling/bin/xcpp",
      "-f",
      "{connection_file}",
      "-std=c++14",
      "-L/home/spring/miniconda2/envs/cling/lib"
  ],
  "language": "C++14"
}

7. xeus-cling for OpenCV

xeus-cling 에서 라이브러리의 로드는 아래의 명령으로 한다.

#pragma cling load("libname")

Jupyter 에서 imshowJupyter에 떠야 하기 때문에, imreadURL을 통해 이미지를 입력받는 것이 편하기 때문에 아래의 파일을 만들고 이를 opencv2/opencv.hpp 에서 include 시키면 된다.

xeus.h

#ifndef XEUS_H
#define XEUS_H
#include<string>
#include<fstream>
#include<iostream>
#include"../xtl/xbase64.hpp"
#include"../xeus/xjson.hpp"
namespace cv{
        void imshow(std::string name,cv::Mat img){
                std::cout << name << std::endl;
                cv::imwrite("/tmp/a.png",img);
                std::ifstream fin("/tmp/a.png",std::ios::binary);
                std::stringstream buffer;
                buffer << fin.rdbuf();
                xeus::xjson mime;
                mime["image/png"]=xtl::base64encode(buffer.str());
                xeus::get_interpreter().display_data(
                    std::move(mime)
                    ,xeus::xjson::object()
                    ,xeus::xjson::object());
                remove("/tmp/a.png");
        }
        cv::Mat imread(const char* url){
                std::ostringstream oss;
                oss <<"curl -L " << url << " -o /tmp/b.png";
                system(oss.str().c_str());
                cv::Mat img=cv::imread("/tmp/b.png",IMREAD_COLOR);
                remove("/tmp/b.png");
                return img;
        }
}
#endif

xeus_c.h

#ifndef XEUS_C_H
#define XEUS_C_H
#include"../opencv2/opencv.hpp"
#define CV_LOAD_IMAGE_COLOR 0.1F
#define CV_LOAD_IMAGE_GRAYSCALE -0.1F
IplImage* cvLoadImage(const char* url,float alpha=0.1F){
    char buf[512]={0};
    sprintf(buf,"curl -L %s -o /tmp/c.jpg",url);
    system(buf);
    if(alpha>0.0F){
        return cvLoadImage("/tmp/c.jpg",1);
    }else{
        return cvLoadImage("/tmp/c.jpg",0);
    }
}
void cvShowImage(const char* window,const IplImage* img){
    cv::Mat mat=cv::cvarrToMat(img);
    cv::imshow(window,mat);
}
/*
#define printf(fmt, ...)        do{char buf[2048];sprintf(buf,fmt, __VA_ARGS__);std::cout << buf;}while(0)
#define puts(str)               do{char buf[2048];sprintf(buf,str);std::cout << buf << std::endl;}while(0)
#define putchar(c)              do{char buf[3];sprintf(buf,"%c",c);std::cout << buf;}while(0)*/
#endif

라이브러리 로드도 귀찮으니 모두 opencv/cv.hopencv2/opencv.hpp 에 아래 구문을 추가한다.

#pragma cling load("libopencv_world")

6. 백그라운드로 jupyter 실행

jupyter notebook --allow-root
Ctrl + Z
bg
disown -h

References

SSL

profile
Researcher & Developer @ NAVER Corp | Designer @ HONGIK Univ.

0개의 댓글