Joeの精進記録

旧:競プロ練習記録

S2V-DQNをCPU環境で動かす

github.com

オリジナルの説明が全然役に立たないのでまとめ直す。

1. Build

1.1

git clone --recursive https://github.com/Hanjun-Dai/graph_comb_opt

唯一そのままでうまく動く

1.2 Build graphnn

github.com

一応こちらの説明に沿ってやる

1.2.1 CUDAをhttps://developer.nvidia.com/cuda-toolkitからダウンロードしインストールする

GPUが入ってなくても大丈夫。CPU環境で動かすのでそもそも必要ないと思うけどdependencyを気にするのが面倒だったのでとりあえず入れておいた。

1.2.2 .zshrc (.bashrc)を更新

export CUDA_HOME=/usr/local/cuda
export LD_LIBRARY_PATH=/usr/local/cuda/lib64:$LD_LIBRARY_PATH
export LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH

CUDA_HOMEは実際ここにちゃんとインストールされるはずなのでそのままで大丈夫

1.2.3 Intel MKLをhttps://software.intel.com/en-us/mkl/choose-downloadからダウンロードしてインストールする

インストール先のディレクトリは標準で/opt/intel以下になる。

source /opt/intel/bin/compilervars.sh -arch intel64 -platform mac

を同様に.zshrc (.bashrc)に追記する。

1.2.4 Intel TBBを入れる

ompみたいなやつ。brew install tbbする。

1.2.5 make_commonを用意する

dir_guard = @mkdir -p $(@D)

INTEL_ROOT := /opt/intel
MKL_ROOT = $(INTEL_ROOT)/mkl
TBB_ROOT = /usr/local
USE_GPU = 0

FIND := find
CXX := g++
CXXFLAGS += -Wall -O3 -std=c++11
LDFLAGS += -lm  -lmkl_rt -ltbb
ifeq ($(USE_GPU), 1)
    CUDA_HOME := /usr/local/cuda
    NVCC := $(CUDA_HOME)/bin/nvcc
    NVCCFLAGS += --default-stream per-thread
    LDFLAGS += -L$(CUDA_HOME)/lib64 -lcudart -lcublas -lcurand -lcusparse
endif

CUDA_ARCH :=    -gencode arch=compute_30,code=sm_30 \
        -gencode arch=compute_35,code=sm_35 \
        -gencode arch=compute_50,code=sm_50 \
        -gencode arch=compute_50,code=compute_50

USE_GPU = 0にする。コンパイラを変える場合はCXXの部分を変更する。 INTEL_ROOT, TBB_ROOTを調整する。

1.2.6 Makefileを変更する

include make_common

ifeq ($(USE_GPU), 1)
    build_root = build
else
    build_root = build_cpuonly
endif

include_dirs = $(CUDA_HOME)/include $(MKL_ROOT)/include $(TBB_ROOT)/include include
CXXFLAGS += $(addprefix -I,$(include_dirs))
CXXFLAGS += -fPIC

# cpp_files = $(shell $(FIND) src/ -name "*.cpp" -printf "%P\n")
cpp_files = nn/hit_at_k.cpp nn/optimizer.cpp nn/sparse_dense_matmul.cpp nn/cross_entropy.cpp nn/in_top_k.cpp nn/elewise_mul.cpp nn/sigmoid.cpp nn/param_set.cpp nn/inner_product.cpp nn/entropy.cpp nn/tanh.cpp nn/type_cast.cpp nn/binary_logloss.cpp nn/axpby.cpp nn/matmul.cpp nn/exp.cpp nn/relu.cpp nn/square_error.cpp nn/multi_matmul.cpp nn/elewise_minus.cpp nn/identity.cpp nn/fully_connected.cpp nn/jagged_softmax.cpp nn/kxplusb.cpp nn/moving_norm.cpp nn/softmax.cpp nn/is_equal.cpp nn/concat_cols.cpp nn/elewise_add.cpp nn/one_hot.cpp nn/variable.cpp nn/arg_max.cpp nn/factor_graph.cpp nn/row_selection.cpp nn/l2_col_norm.cpp nn/reduce.cpp nn/abs_error.cpp nn/multinomial_sample.cpp nn/msg_pass.cpp nn/nat_log.cpp nn/reduce_mean.cpp util/fmt.cpp util/mem_holder.cpp util/graph_struct.cpp tensor/cpu_row_sparse_tensor.cpp tensor/cpu_sparse_tensor.cpp tensor/cpu_dense_tensor.cpp tensor/t_shape.cpp tensor/t_data.cpp tensor/tensor.cpp
cxx_obj_files = $(subst .cpp,.o,$(cpp_files))
obj_build_root = $(build_root)/objs
objs = $(addprefix $(obj_build_root)/cxx/,$(cxx_obj_files))

ifeq ($(USE_GPU), 1)
    CXXFLAGS += -DUSE_GPU
    NVCCFLAGS += -DUSE_GPU
    NVCCFLAGS += $(addprefix -I,$(include_dirs))
    NVCCFLAGS += -std=c++11 --use_fast_math --compiler-options '-fPIC'
    cu_files = $(shell $(FIND) src/ -name "*.cu" -printf "%P\n")
    cu_obj_files = $(subst .cu,.o,$(cu_files))
    objs += $(addprefix $(obj_build_root)/cuda/,$(cu_obj_files))
endif

DEPS = ${objs:.o=.d}

lib_dir = $(build_root)/lib
gnn_lib = $(lib_dir)/libgnn.a

# test_src = $(shell $(FIND) test/ -name "*.cpp" -printf "%P\n")
test_src = cuda_test.cpp cpu_row_sparse_test.cpp test_main.cpp op_test.cpp gpu_tensor_test.cpp simple_test.cpp cpu_tensor_test.cpp
test_objs = $(subst .cpp,.o,$(test_src))
test_build_root = $(build_root)/test
test_target = $(addprefix $(test_build_root)/,$(test_objs))
DEPS += ${test_target:.o=.d}

all: $(gnn_lib)

$(gnn_lib): $(objs)
    $(dir_guard)
    ar rcs $@ $(objs)

ifeq ($(USE_GPU), 1)
$(obj_build_root)/cuda/%.o: src/%.cu
    $(dir_guard)
    $(NVCC) $(NVCCFLAGS) $(CUDA_ARCH) -M $< -o ${@:.o=.d} -odir $(@D)
    $(NVCC) $(NVCCFLAGS) $(CUDA_ARCH) -c $< -o $@
endif

$(obj_build_root)/cxx/%.o: src/%.cpp
    $(dir_guard)
    $(CXX) $(CXXFLAGS) -MMD -c -o $@ $(filter %.cpp, $^)

.PHONY: test

test: $(test_build_root)/test_main
    ./$(test_build_root)/test_main

$(test_build_root)/%.o: test/%.cpp
    $(dir_guard)
    $(CXX) $(CXXFLAGS) -MMD -c -o $@ $(filter %.cpp, $^)

$(test_build_root)/test_main: test/test_main.cpp $(test_target) $(gnn_lib)
    $(dir_guard)
    $(CXX) $(CXXFLAGS) -MMD -o $@ $(filter %.o, $^) -L$(lib_dir) -lgnn $(LDFLAGS) -lpthread -lgtest

clean:
    rm -rf $(build_root)

-include $(DEPS)

cpp_filestest_filesを(FIND)によって得る方法がLinuxのみの対応なのでもう全部書いちゃう。

1.2.7 ソースコードの変更

include/tensor/tensor.hのヘッダに #include <functional>を追加する。

diffの詳細はこんな感じ。

 #include <memory>
 #include <iostream>
 #include <exception>
+#include <functional>
 #include <string>

1.2.8 Make

これでやっとmakeが通る

1.3 S2V-DQNのbuild

1.3.1 Makefileの変更

GNN_HOME=../../../graphnn

include $(GNN_HOME)/make_common

lib_dir = $(GNN_HOME)/build_cpuonly/lib
gnn_lib = $(lib_dir)/libgnn.a

include_dirs = $(CUDA_HOME)/include $(MKL_ROOT)/include $(GNN_HOME)/include ./include

CXXFLAGS += $(addprefix -I,$(include_dirs)) -Wno-unused-local-typedef
CXXFLAGS += -fPIC
# CXXFLAGS += -fPIC -DUSE_GPU
# CXXFLAGS += -DGPU_MODE
# cpp_files = $(shell $(FIND) src/lib -name "*.cpp" -printf "%P\n")
cpp_files = nstep_replay_mem.cpp simulator.cpp mvc_env.cpp graph.cpp config.cpp qnet.cpp inet.cpp nn_api.cpp
cxx_obj_files = $(subst .cpp,.o,$(cpp_files))

objs = $(addprefix build/lib/,$(cxx_obj_files))
DEPS = $(objs:.o=.d)

target = build/dll/libmvc.so
target_dep = $(addsuffix .d,$(target))

.PRECIOUS: build/lib/%.o

all: $(target)

build/dll/libmvc.so : src/mvc_lib.cpp $(gnn_lib) $(objs)
    $(dir_guard)
    $(CXX) -shared $(CXXFLAGS) -MMD -o $@ $(filter %.cpp %.o, $^) -L$(lib_dir) -lgnn $(LDFLAGS)

DEPS += $(target_dep)

build/lib/%.o: src/lib/%.cpp
    $(dir_guard)
    $(CXX) $(CXXFLAGS) -MMD -c -o $@ $(filter %.cpp, $^)

clean:
    rm -rf build

-include $(DEPS)

buildをbuild_cpuonlyに変更する。とりあえず、GPUを使いそうなところをコメントアウトし、cpp_filesを直書きする。

1.3.2 Make

makeが通るはず。

追記:通らなかったら.zshrcをもう一度sourceしてみて

1.3.3 PythonをPython2に変える。

code/data_generator/mvc/run_generate.shcode/s2v_mvc/run_nstep_dqn.shpythonの部分をpython2にする。まあpyenvとかを調整してもいい。

1.3.4 必要なモジュールをインストールする。

入ってないかもしれなそうなモジュールはnetworkxとtqdm いずれもpipでインストールできる。

rpathを追加

このままだと.soファイルがうまく動かないので

$ install_name_tool -add_rpath /opt/intel/mkl/lib mvc_lib/build/dll/libmvc.so

する。mklは/opt/intel以下にあると思うけど違ったら適宜直して。

2. Experiments on synthetic data

動くと思う