diff --git a/.bazelrc b/.bazelrc index 4b603b72..b223c308 100644 --- a/.bazelrc +++ b/.bazelrc @@ -1,11 +1,20 @@ +build --enable_runfiles build --action_env=BAZEL_LINKLIBS=-l%:libstdc++.a:-lm build --action_env=BAZEL_LINKOPTS=-static-libgcc build --action_env=CUDA_DIR=/usr/local/cuda -build --incompatible_strict_action_env --cxxopt=-std=c++17 --host_cxxopt=-std=c++17 --client_env=BAZEL_CXXOPTS=-std=c++17 +build --incompatible_strict_action_env + +build:linux --cxxopt=-std=c++17 --host_cxxopt=-std=c++17 --client_env=BAZEL_CXXOPTS=-std=c++17 + build:debug --cxxopt=-DENVPOOL_TEST --compilation_mode=dbg -s build:test --cxxopt=-DENVPOOL_TEST --copt=-g0 --copt=-O3 --copt=-DNDEBUG --copt=-msse --copt=-msse2 --copt=-mmmx -build:release --copt=-g0 --copt=-O3 --copt=-DNDEBUG --copt=-msse --copt=-msse2 --copt=-mmmx +build:release --copt=-g0 --copt=-O3 --copt=-DNDEBUG --copt=-msse --copt=-msse2 --copt=-mmmx + +# modified for win32 +build:win32 --cxxopt=/std:c++17 --host_cxxopt=/std:c++17 --client_env=BAZEL_CXXOPTS=/std:c++17 +build:win32 --compiler=clang-cl --copt=-DWIN32 +build:win32 --action_env=CUDA_DIR="C:/Program Files/NVIDIA GPU Computing Toolkit/CUDA/v11.7" build:clang-tidy --aspects @bazel_clang_tidy//clang_tidy:clang_tidy.bzl%clang_tidy_aspect build:clang-tidy --@bazel_clang_tidy//:clang_tidy_config=//:clang_tidy_config -build:clang-tidy --output_groups=report +build:clang-tidy --output_groups=report \ No newline at end of file diff --git a/BUILD b/BUILD index 8050ac27..bc056945 100644 --- a/BUILD +++ b/BUILD @@ -22,3 +22,4 @@ py_binary( requirement("wheel"), ], ) + diff --git a/CPPLINT.cfg b/CPPLINT.cfg deleted file mode 100644 index aa112bc3..00000000 --- a/CPPLINT.cfg +++ /dev/null @@ -1 +0,0 @@ -filter=-build/c++11,+build/c++17,-build/include_subdir diff --git a/WINDOWS.md b/WINDOWS.md new file mode 100644 index 00000000..32c72760 --- /dev/null +++ b/WINDOWS.md @@ -0,0 +1,44 @@ +# Windows Migration + +Note that this merge request only intends to work on Windows. I haven't write code that switch support between linux and Windows. I'll update that feature after the whole thing can be build on Windows. + +## Setup Environment On Windows + +1. Install [Windows Powershell](https://learn.microsoft.com/en-us/powershell/scripting/install/installing-powershell-on-windows?view=powershell-7.2). Do step 2 and 3 in Powershell. +2. Install [choco](https://chocolatey.org/install#individual) +3. Install bazelisk/bazel ``` choco install bazelisk``` +4. Install [MinGW-w64](https://www.mingw-w64.org/) or via [released version](https://winlibs.com/#download-release) +5. Install [git bash](https://gitforwindows.org/) and make sure it uses MINGW64 emulation. Do all the following steps in bash. +6. Install [VC++ 2017](https://www.google.com/url?q=https://aka.ms/vs/15/release/vs_buildtools.exe&sa=D&source=docs&ust=1667504254128145&usg=AOvVaw3jOTmoHfuzAHgaScSgsmlE) on Windows +7. Install python 3.10 (instead of 3.11 because pygame installation fails on Windows) +8. Go where python.exe is installed, make a copy of python.exe and rename it python3.exe (it would bypass the error "python interpreter cannot be found with requirement") +9. Install [swig.exe](https://sourceforge.net/projects/swig/files/swigwin/swigwin-4.1.0/swigwin-4.1.0.zip/download?use_mirror=gigenet) and merge it into python folder and do [some hacks](https://stackoverflow.com/questions/44504899/installing-pocketsphinx-python-module-command-swig-exe-failed) +10. Install [Clang](https://bazel.build/configure/windows#using) and follow this [link](https://github.com/llvm/llvm-project/releases/tag/llvmorg-15.0.2). Don't forget to set BAZEL_VC and BAZEL_LLVM in environmental variable manually. +11. Now you can run some tests below + + + + + +## Run Tests +- Dummy +```bazel build --test_output=all //envpool/dummy:dummy --config=debug --config=win32 ``` +```bazel build --test_output=all //envpool/dummy:dummy_envpool_test --config=debug --config=win32``` + +- Utils +- Box2d +```bazel build --test_output=all //envpool/box2d:box2d --config=debug --config=win32``` +```bazel build --test_output=all //envpool/box2d:box2d_deterministic_test --config=debug --config=win32``` +- Classic Control +- Toy_text +- Mujoco +```bazel build --test_output=all //envpool/mujoco:mujoco_dmc_env --config=debug --config=win32``` +```bazel build --test_output=all //envpool/mujoco:mujoco_dmc --config=debug a--config=win32``` +```bazel build --test_output=all //envpool/mujoco:mujoco_gym_env --config=debug --config=win32``` +```bazel build --test_output=all //envpool/mujoco:mujoco_gym --config=debug --config=win32``` +- Atari:atari_env + + +## TODO +- Atari:atari (Stuck on building opencv) +- Make a windows docker diff --git a/docs/content/build.rst b/docs/content/build.rst index 022a6d56..612b3193 100644 --- a/docs/content/build.rst +++ b/docs/content/build.rst @@ -86,7 +86,7 @@ It also requires **Python version >= 3.7**: sudo apt install -y python3-dev python3-pip sudo ln -sf /usr/bin/python3 /usr/bin/python -Install CUDA to enable XLA: see https://developer.nvidia.com/cuda-downloads +Install CUDA to enable XLA: see https://developer.nvidia.com/-downloads Install other dependencies: see `Dockerfile `_. diff --git a/envpool/classic_control/classic_control.cc b/envpool/classic_control/classic_control.cc index 380a3b47..cd6d287b 100644 --- a/envpool/classic_control/classic_control.cc +++ b/envpool/classic_control/classic_control.cc @@ -12,6 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. +# define M_PI 3.14159265358979323846 //GNU extension is not loaded on MinGW #include "envpool/classic_control/acrobot.h" #include "envpool/classic_control/cartpole.h" #include "envpool/classic_control/mountain_car.h" diff --git a/envpool/core/BUILD b/envpool/core/BUILD index fd57eee4..c59b121e 100644 --- a/envpool/core/BUILD +++ b/envpool/core/BUILD @@ -171,6 +171,7 @@ cc_library( ], ) +# if windows, makes up a dummy xla without cuda dependency cc_library( name = "xla_template", hdrs = ["xla_template.h"], @@ -183,6 +184,7 @@ cc_library( ], ) + cc_library( name = "xla", hdrs = ["xla.h"], @@ -198,6 +200,6 @@ pybind_library( hdrs = ["py_envpool.h"], deps = [ ":envpool", - ":xla", + ":xla" ], ) diff --git a/envpool/core/array.h b/envpool/core/array.h index e99cd51b..657152f0 100644 --- a/envpool/core/array.h +++ b/envpool/core/array.h @@ -156,10 +156,10 @@ class Array { * memory of this Array. */ template - void Assign(const T* buff, std::size_t sz) const { + void Assign(const T buff, std::size_t sz) const { DCHECK_EQ(sz, size) << " assignment size mismatch"; DCHECK_EQ(sizeof(T), element_size) << " element size mismatch"; - std::memcpy(ptr_.get(), buff, sz * sizeof(T)); + std::memcpy(ptr_.get(), &buff, sz * sizeof(T)); } /** diff --git a/envpool/core/async_envpool.h b/envpool/core/async_envpool.h index 089f998f..b09365b6 100644 --- a/envpool/core/async_envpool.h +++ b/envpool/core/async_envpool.h @@ -106,14 +106,19 @@ class AsyncEnvPool : public EnvPool { if (spec.config["thread_affinity_offset"_] >= 0) { std::size_t thread_affinity_offset = spec.config["thread_affinity_offset"_]; - for (std::size_t tid = 0; tid < num_threads_; ++tid) { - cpu_set_t cpuset; - CPU_ZERO(&cpuset); - std::size_t cid = (thread_affinity_offset + tid) % processor_count; - CPU_SET(cid, &cpuset); - pthread_setaffinity_np(workers_[tid].native_handle(), sizeof(cpu_set_t), - &cpuset); - } + + // The following does not work under Windows. Need to find alternatives. + #ifdef __linux__ + for (std::size_t tid = 0; tid < num_threads_; ++tid) { + cpu_set_t cpuset; + CPU_ZERO(&cpuset); + std::size_t cid = (thread_affinity_offset + tid) % processor_count; + CPU_SET(cid, &cpuset); + pthread_setaffinity_np(workers_[tid].native_handle(), sizeof(cpu_set_t), + &cpuset); + } + #endif + } } diff --git a/envpool/core/state_buffer_queue.h b/envpool/core/state_buffer_queue.h index 56f946c3..d4b779f9 100644 --- a/envpool/core/state_buffer_queue.h +++ b/envpool/core/state_buffer_queue.h @@ -83,7 +83,10 @@ class StateBufferQueue { } std::size_t processor_count = std::thread::hardware_concurrency(); // hardcode here :( - std::size_t create_buffer_thread_num = std::max(1UL, processor_count / 64); + std::size_t create_buffer_thread_num = 1; + if (processor_count / 64 > create_buffer_thread_num){ + create_buffer_thread_num = processor_count / 64; + } for (std::size_t i = 0; i < create_buffer_thread_num; ++i) { create_buffer_thread_.emplace_back(std::thread([&]() { while (true) { diff --git a/envpool/core/xla.h b/envpool/core/xla.h index a6463bb2..725d2045 100644 --- a/envpool/core/xla.h +++ b/envpool/core/xla.h @@ -17,6 +17,7 @@ #ifndef ENVPOOL_CORE_XLA_H_ #define ENVPOOL_CORE_XLA_H_ + #include #include @@ -29,6 +30,9 @@ #include "envpool/core/array.h" #include "envpool/core/xla_template.h" + + + template constexpr bool is_container_v = false; // NOLINT template diff --git a/envpool/core/xla_template.h b/envpool/core/xla_template.h index 2da813db..b964b070 100644 --- a/envpool/core/xla_template.h +++ b/envpool/core/xla_template.h @@ -17,7 +17,7 @@ #ifndef ENVPOOL_CORE_XLA_TEMPLATE_H_ #define ENVPOOL_CORE_XLA_TEMPLATE_H_ -#include +#include "cuda_runtime_api.h" #include #include #include @@ -109,6 +109,7 @@ struct CustomCall { return std::make_tuple( py::capsule(reinterpret_cast(Cpu), "xla._CUSTOM_CALL_TARGET"), py::capsule(reinterpret_cast(Gpu), "xla._CUSTOM_CALL_TARGET")); + } static auto Xla(Class* obj) { diff --git a/envpool/mujoco/BUILD b/envpool/mujoco/BUILD index e528c5ff..553b1126 100644 --- a/envpool/mujoco/BUILD +++ b/envpool/mujoco/BUILD @@ -19,11 +19,17 @@ genrule( genrule( name = "gen_mujoco_so", - srcs = ["@mujoco//:mujoco_so"], + srcs = select({ + "@bazel_tools//src/conditions:linux": ["@mujoco_linux//:mujoco_so"], + "@bazel_tools//src/conditions:windows": ["@mujoco_windows//:mujoco_so"], + }), + outs = ["libmujoco.so.2.2.1"], cmd = "cp $< $@", ) + + cc_library( name = "mujoco_gym_env", hdrs = [ @@ -44,9 +50,12 @@ cc_library( ":gen_mujoco_gym_xml", ], deps = [ - "//envpool/core:async_envpool", - "@mujoco//:mujoco_lib", - ], + "//envpool/core:async_envpool", + ] + select({ + "@bazel_tools//src/conditions:linux": ["@mujoco_linux//:mujoco_lib"], + "@bazel_tools//src/conditions:windows": ["@mujoco_windows//:mujoco_lib"], + }), + ) pybind_extension( @@ -86,11 +95,10 @@ cc_library( "dmc/walker.h", ], data = [":gen_mujoco_dmc_xml"], - deps = [ - "//envpool/core:async_envpool", - "@mujoco//:mujoco_lib", - "@pugixml", - ], + deps = ["//envpool/core:async_envpool", "@pugixml"] + select({ + "@bazel_tools//src/conditions:linux": ["@mujoco_linux//:mujoco_lib"], + "@bazel_tools//src/conditions:windows": ["@mujoco_windows//:mujoco_lib"], + }) ) pybind_extension( diff --git a/envpool/mujoco/dmc/mujoco_env.cc b/envpool/mujoco/dmc/mujoco_env.cc index b4d4faa0..4764cfa2 100644 --- a/envpool/mujoco/dmc/mujoco_env.cc +++ b/envpool/mujoco/dmc/mujoco_env.cc @@ -12,6 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. + #include "envpool/mujoco/dmc/mujoco_env.h" #include @@ -50,7 +51,7 @@ MujocoEnv::MujocoEnv(const std::string& base_path, const std::string& raw_xml, std::memcpy(vfs->filedata[vfs->nfile - 1], content.c_str(), content.size()); } // create model and data - model_ = mj_loadXML(model_filename.c_str(), vfs.get(), error_.begin(), 1000); + model_ = mj_loadXML(model_filename.c_str(), vfs.get(), &error_[0] , 1000); // change error to bypass compiler error data_ = mj_makeData(model_); #ifdef ENVPOOL_TEST qpos0_.reset(new mjtNum[model_->nq]); @@ -180,7 +181,7 @@ void MujocoEnv::RandomizeLimitedAndRotationalJoints(std::mt19937* gen) { axis[2] * axis[2]); axis = {axis[0] / norm, axis[1] / norm, axis[2] / norm}; auto angle = RandUniform(0, range_max)(*gen); - mju_axisAngle2Quat(data_->qpos + qpos_offset, axis.begin(), angle); + mju_axisAngle2Quat(data_->qpos + qpos_offset, &axis[0], angle); // bypass compiler error } } else if (joint_type == mjJNT_HINGE) { data_->qpos[qpos_offset] = RandUniform(-M_PI, M_PI)(*gen); diff --git a/envpool/mujoco/dmc/mujoco_env.h b/envpool/mujoco/dmc/mujoco_env.h index 4e4434a1..595f834f 100644 --- a/envpool/mujoco/dmc/mujoco_env.h +++ b/envpool/mujoco/dmc/mujoco_env.h @@ -14,6 +14,7 @@ * limitations under the License. */ +# define M_PI 3.14159265358979323846 //GNU extension is not loaded on MinGW #ifndef ENVPOOL_MUJOCO_DMC_MUJOCO_ENV_H_ #define ENVPOOL_MUJOCO_DMC_MUJOCO_ENV_H_ @@ -23,6 +24,7 @@ #include #include #include +#include #include "envpool/mujoco/dmc/utils.h" diff --git a/envpool/mujoco/gym/mujoco_env.h b/envpool/mujoco/gym/mujoco_env.h index cf70a8c8..03d0828a 100644 --- a/envpool/mujoco/gym/mujoco_env.h +++ b/envpool/mujoco/gym/mujoco_env.h @@ -43,7 +43,7 @@ class MujocoEnv { public: MujocoEnv(const std::string& xml, int frame_skip, bool post_constraint, int max_episode_steps) - : model_(mj_loadXML(xml.c_str(), nullptr, error_.begin(), 1000)), + : model_(mj_loadXML(xml.c_str(), nullptr, &error_[0], 1000)), data_(mj_makeData(model_)), init_qpos_(new mjtNum[model_->nq]), init_qvel_(new mjtNum[model_->nv]), diff --git a/envpool/toy_text/BUILD b/envpool/toy_text/BUILD index 1bf879ea..573f4c08 100644 --- a/envpool/toy_text/BUILD +++ b/envpool/toy_text/BUILD @@ -26,6 +26,7 @@ pybind_extension( deps = [ ":toy_text_env", "//envpool/core:py_envpool", + "//envpool/core:xla", ], ) diff --git a/envpool/workspace0.bzl b/envpool/workspace0.bzl index ea447b96..7805f297 100644 --- a/envpool/workspace0.bzl +++ b/envpool/workspace0.bzl @@ -18,6 +18,7 @@ load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") load("@bazel_tools//tools/build_defs/repo:utils.bzl", "maybe") load("//third_party/cuda:cuda.bzl", "cuda_configure") + def workspace(): """Load requested packages.""" maybe( @@ -316,17 +317,30 @@ def workspace(): build_file = "//third_party/vizdoom_extra_maps:vizdoom_extra_maps.BUILD", ) + # mujoco linux + maybe( http_archive, - name = "mujoco", + name = "mujoco_linux", sha256 = "d1cb3a720546240d894cd315b7fd358a2b96013a1f59b6d718036eca6f6edac2", strip_prefix = "mujoco-2.2.1", urls = [ - "https://github.com/deepmind/mujoco/releases/download/2.2.1/mujoco-2.2.1-linux-x86_64.tar.gz", - "https://ml.cs.tsinghua.edu.cn/~jiayi/envpool/deepmind/mujoco/mujoco-2.2.1-linux-x86_64.tar.gz", - ], + "https://github.com/deepmind/mujoco/releases/download/2.2.1/mujoco-2.2.1-linux-x86_64.tar.gz", + "https://ml.cs.tsinghua.edu.cn/~jiayi/envpool/deepmind/mujoco/mujoco-2.2.1-linux-x86_64.tar.gz", + ], + build_file = "//third_party/mujoco:mujoco.BUILD", + ) + + + # mujoco windows + maybe( + http_archive, + name = "mujoco_windows", + sha256 = "e0068d25fdb00ec3afa53e429b5eff438d222455603bafa080086abaf11fe16f", + urls = ["https://github.com/deepmind/mujoco/releases/download/2.2.1/mujoco-2.2.1-windows-x86_64.zip"], build_file = "//third_party/mujoco:mujoco.BUILD", ) + maybe( http_archive, diff --git a/third_party/cuda/cuda.bzl b/third_party/cuda/cuda.bzl index c295afd7..ba12886e 100644 --- a/third_party/cuda/cuda.bzl +++ b/third_party/cuda/cuda.bzl @@ -17,13 +17,30 @@ _CUDA_DIR = "CUDA_DIR" def _impl(rctx): - cuda_dir = rctx.os.environ.get(_CUDA_DIR, default = "/usr/local/cuda") - rctx.symlink("{}/include".format(cuda_dir), "include") - rctx.symlink("{}/lib64".format(cuda_dir), "lib64") - rctx.file("WORKSPACE") - rctx.file("BUILD", content = """ + if "windows" in rctx.os.name: + cuda_dir = rctx.os.environ.get(_CUDA_DIR, default = "C:/Program Files/NVIDIA GPU Computing Toolkit/CUDA/v11.7") + rctx.symlink("{}/include".format(cuda_dir), "include") + rctx.symlink("{}/lib".format(cuda_dir), "lib") + rctx.file("WORKSPACE") + rctx.file("BUILD", content = """ +package(default_visibility = ["//visibility:public"]) +cc_library( + name = "cudart_static", + srcs = ["lib/x64/cudart_static.lib"], + hdrs = glob([ + "include/*.h", + "include/**/*.h", + ]), + strip_include_prefix = "include", +) + """) + else: + cuda_dir = rctx.os.environ.get(_CUDA_DIR, default = "/usr/local/cuda") + rctx.symlink("{}/include".format(cuda_dir), "include") + rctx.symlink("{}/lib64".format(cuda_dir), "lib64") + rctx.file("WORKSPACE") + rctx.file("BUILD", content = """ package(default_visibility = ["//visibility:public"]) - cc_library( name = "cudart_static", srcs = ["lib64/libcudart_static.a"], @@ -33,7 +50,8 @@ cc_library( ]), strip_include_prefix = "include", ) -""") + """) + cuda_configure = repository_rule( implementation = _impl, diff --git a/third_party/mujoco/mujoco.BUILD b/third_party/mujoco/mujoco.BUILD index e000bcc5..d0058e2e 100644 --- a/third_party/mujoco/mujoco.BUILD +++ b/third_party/mujoco/mujoco.BUILD @@ -14,5 +14,8 @@ cc_library( filegroup( name = "mujoco_so", - srcs = ["lib/libmujoco.so.2.2.1"], + srcs = select({ + "@bazel_tools//src/conditions:linux": ["lib/libmujoco.so.2.2.1"], + "@bazel_tools//src/conditions:windows": ["lib/mujoco.lib"], + }), ) diff --git a/third_party/opencv/opencv.BUILD b/third_party/opencv/opencv.BUILD index 69510941..c2be2918 100644 --- a/third_party/opencv/opencv.BUILD +++ b/third_party/opencv/opencv.BUILD @@ -64,11 +64,19 @@ cmake( "-ldl", ], out_include_dir = "include/opencv4", - out_static_libs = [ - "libopencv_imgproc.a", - "libopencv_features2d.a", - "libopencv_flann.a", - "libopencv_core.a", - ], + out_static_libs = select({ + "@bazel_tools//src/conditions:linux": [ + "libopencv_imgproc.a", + "libopencv_features2d.a", + "libopencv_flann.a", + "libopencv_core.a", + ], + "@bazel_tools//src/conditions:windows": [ + "libopencv_imgproc.lib", + "libopencv_features2d.lib", + "libopencv_flann.lib", + "libopencv_core.lib", + ], + }), visibility = ["//visibility:public"], ) diff --git a/third_party/vizdoom/vizdoom.BUILD b/third_party/vizdoom/vizdoom.BUILD index f197e4f7..b383f432 100644 --- a/third_party/vizdoom/vizdoom.BUILD +++ b/third_party/vizdoom/vizdoom.BUILD @@ -211,7 +211,6 @@ cc_library( copts = [ "-DNEED_ITOA=1", "-Wall", - "-Wno-pointer-sign", "-Wno-uninitialized", "-Wno-unused-but-set-variable", "-include $(execpath @glibc_version_header//:glibc_2_17)",