├── .gitignore ├── .gitmodules ├── CMakeLists.txt ├── LICENSE ├── README.md ├── data └── bfs │ └── simple.txt ├── example ├── CMakeLists.txt ├── bfs │ ├── CMakeLists.txt │ ├── bfs_const_size_array.cc │ ├── bfs_const_size_array.cu │ ├── bfs_inlined_dynamic_array.cc │ ├── bfs_loader.h │ └── bfs_std_vector.cc ├── n_body.cc ├── particle_simulation.cc └── traffic │ ├── CMakeLists.txt │ ├── benchmark.h │ ├── configuration.h │ ├── entities │ ├── car.inc │ ├── cell.inc │ ├── priority_yield_traffic_controller.inc │ ├── shared_signal_group.inc │ ├── simulation.inc │ └── traffic_light.inc │ ├── run_bench_traffic.sh │ ├── simulation_adapter.cu │ ├── simulation_adapter.h │ ├── simulation_converter.inc │ ├── statistics.inc │ └── traffic.cu ├── ikra ├── CMakeLists.txt ├── executor │ ├── cuda_executor.h │ ├── executor.h │ ├── iterator.h │ └── util.h └── soa │ ├── CMakeLists.txt │ ├── addressable_field_shared.inc │ ├── array_field.h │ ├── array_shared.inc │ ├── class_initialization.h │ ├── constants.h │ ├── cuda.h │ ├── field.h │ ├── field_shared.inc │ ├── field_type_generator.h │ ├── layout.h │ ├── partially_inlined_array_field.h │ ├── preprocessor.h │ ├── soa.h │ ├── storage.h │ └── util.h └── test ├── CMakeLists.txt ├── array_cuda_test.cu ├── executor_test.cc ├── executor_test_layout.inc ├── minimum_cuda_test.cu └── soa ├── array_test.cc ├── array_test_layout.inc ├── basic_class_test.cc ├── basic_class_test_layout.inc ├── benchmarks ├── .gitignore ├── array │ ├── aos_style.cu │ ├── aos_style_cpu.cc │ ├── benchmark.h │ ├── configuration.h │ ├── inlined_soa_style.cu │ └── soa_style.cu ├── assembly │ ├── clang++-5.0_-O0_DynamicStorage_0_Soa.S │ ├── clang++-5.0_-O0_DynamicStorage_4_Soa.S │ ├── clang++-5.0_-O0_StaticStorage_0_Aos.S │ ├── clang++-5.0_-O0_StaticStorage_0_Soa.S │ ├── clang++-5.0_-O0_StaticStorage_4_Soa.S │ ├── clang++-5.0_-O3_DynamicStorage_0_Soa.S │ ├── clang++-5.0_-O3_DynamicStorage_4_Soa.S │ ├── clang++-5.0_-O3_StaticStorage_0_Aos.S │ ├── clang++-5.0_-O3_StaticStorage_0_Soa.S │ ├── clang++-5.0_-O3_StaticStorage_4_Soa.S │ ├── clang++-5.0_nbody_aos.S │ ├── clang++-5.0_nbody_ikracpp.S │ ├── clang++-5.0_nbody_ikracpp_field.S │ ├── clang++-5.0_nbody_ikracpp_inversed.S │ ├── clang++-5.0_nbody_soa.S │ ├── cuda_array_aos_style.S │ ├── cuda_array_inlined_soa_style.S │ ├── cuda_array_soa_style.S │ ├── cuda_codegen_test.S │ ├── cuda_nbody_ikracpp_inversed_field_gpu.S │ ├── cuda_nbody_ikracpp_inversed_gpu.S │ ├── cuda_nbody_soa_inversed_gpu.S │ ├── g++_-O0_DynamicStorage_0_Soa.S │ ├── g++_-O0_DynamicStorage_4_Soa.S │ ├── g++_-O0_StaticStorage_0_Aos.S │ ├── g++_-O0_StaticStorage_0_Soa.S │ ├── g++_-O0_StaticStorage_4_Soa.S │ ├── g++_-O3_DynamicStorage_0_Soa.S │ ├── g++_-O3_DynamicStorage_4_Soa.S │ ├── g++_-O3_StaticStorage_0_Aos.S │ ├── g++_-O3_StaticStorage_0_Soa.S │ ├── g++_-O3_StaticStorage_4_Soa.S │ ├── g++_nbody_aos.S │ ├── g++_nbody_ikracpp.S │ ├── g++_nbody_ikracpp_field.S │ ├── g++_nbody_ikracpp_inversed.S │ └── g++_nbody_soa.S ├── build.sh ├── codegen_test.cc ├── cuda_codegen_test.cu └── nbody │ ├── aos.cc │ ├── benchmark.h │ ├── ikracpp.cc │ ├── ikracpp_field.cc │ ├── ikracpp_inversed.cc │ ├── ikracpp_inversed_field_gpu.cu │ ├── ikracpp_inversed_gpu.cu │ ├── soa.cc │ └── soa_inversed.cu ├── cuda_array_test.cu ├── cuda_inline_array_memcpy_aos_test.cu ├── cuda_inline_array_memcpy_test.cu └── pointer_arithmetics_test.cc /.gitignore: -------------------------------------------------------------------------------- 1 | *.i 2 | *.ii 3 | *.gpu 4 | *.ptx 5 | *.cubin 6 | *.fatbin 7 | 8 | # Prerequisites 9 | *.d 10 | 11 | # Compiled Object files 12 | *.slo 13 | *.lo 14 | *.o 15 | *.obj 16 | 17 | # Precompiled Headers 18 | *.gch 19 | *.pch 20 | 21 | # Compiled Dynamic libraries 22 | *.so 23 | *.dylib 24 | *.dll 25 | 26 | # Fortran module files 27 | *.mod 28 | *.smod 29 | 30 | # Compiled Static libraries 31 | *.lai 32 | *.la 33 | *.a 34 | *.lib 35 | 36 | # Executables 37 | *.exe 38 | *.out 39 | *.app 40 | 41 | test/experiment_test.cc 42 | 43 | # CMake 44 | CMakeCache.txt 45 | CMakeFiles 46 | CMakeScripts 47 | Testing 48 | Makefile 49 | cmake_install.cmake 50 | install_manifest.txt 51 | compile_commands.json 52 | CTestTestfile.cmake 53 | bin/ 54 | *.pc 55 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "lib/googletest"] 2 | path = lib/googletest 3 | url = git@github.com:google/googletest.git 4 | [submodule "example/traffic/traffic-simulation"] 5 | path = example/traffic/traffic-simulation 6 | url = git@github.com:prg-titech/traffic-simulation.git 7 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.2 FATAL_ERROR) 2 | project(ikra-cpp) 3 | 4 | # Set up CUDA 5 | # TODO: -gencode arch=compute_52,code=sm_52 6 | # TODO: This should be CUDA 9.0 but the version check is broken on my machine. 7 | find_package(CUDA 8.0 REQUIRED) 8 | set(CUDA_NVCC_FLAGS ${CUDA_NVCC_FLAGS}; -std=c++11 --expt-extended-lambda) 9 | 10 | set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) 11 | set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) 12 | set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) 13 | 14 | set(CMAKE_CXX_STANDARD 11) 15 | 16 | if(NOT CMAKE_BUILD_TYPE) 17 | set(CMAKE_BUILD_TYPE Debug) 18 | endif() 19 | 20 | set(CMAKE_CXX_FLAGS "-Wall -Wextra") 21 | set(CMAKE_CXX_FLAGS_DEBUG "-g -O0") 22 | set(CMAKE_CXX_FLAGS_RELEASE "-O3 -DNDEBUG -Wno-unused-parameter") 23 | 24 | add_subdirectory(lib/googletest) 25 | enable_testing() 26 | 27 | add_subdirectory(ikra) 28 | add_subdirectory(test) 29 | add_subdirectory(example) 30 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Programming Research Group @ TokyoTech 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Ikra-Cpp 2 | Ikra-Cpp is a C++/CUDA DSL for object-oriented programming with Structure of Arrays (SOA) data layout. Ikra-Cpp provides an AOS-style OOP notation that is similar to standard C++ but layouts data as SOA. This gives programmers the performance benefit of SOA and the expressivness of AOS-style object-oriented programming at the same time. 3 | 4 | ## Example 5 | ```c++ 6 | // N-Body Simulation 7 | // Code adapted from: http://physics.princeton.edu/~fpretori/Nbody/code.htm 8 | 9 | #include "executor/executor.h" 10 | #include "soa/soa.h" 11 | 12 | using namespace std; 13 | using ikra::executor::execute; 14 | using ikra::soa::SoaLayout; 15 | 16 | static const int kNumBodies = 25; 17 | static const double kMaxMass = 1000; 18 | static const double kTimeInterval = 0.5; 19 | static const double kGravityConstant = 6.673e-11; // gravitational constant 20 | static const int kIterations = 1000; 21 | 22 | #define RAND (1.0 * rand() / RAND_MAX) 23 | 24 | class Body : public SoaLayout
{ 25 | public: 26 | IKRA_INITIALIZE_CLASS 27 | 28 | Body(double mass, double pos_x, double pos_y, double vel_x, double vel_y) 29 | : mass_(mass) { 30 | position_[0] = pos_x; 31 | position_[1] = pos_y; 32 | velocity_[0] = vel_x; 33 | velocity_[1] = vel_y; 34 | this->reset_force(); 35 | } 36 | 37 | double_ mass_; 38 | array_(double, 2) position_; 39 | array_(double, 2) velocity_; 40 | array_(double, 2) force_; 41 | 42 | void add_force(Body* body) { 43 | if (this == body) return; 44 | 45 | double EPS = 0.01; // Softening parameter (just to avoid infinities). 46 | double dx = body->position_[0] - position_[0]; 47 | double dy = body->position_[1] - position_[1]; 48 | double dist = sqrt(dx*dx + dy*dy); 49 | double F = kGravityConstant*mass_*body->mass_ / (dist*dist + EPS*EPS); 50 | force_[0] += F*dx / dist; 51 | force_[1] += F*dy / dist; 52 | } 53 | 54 | void add_force_to_all() { 55 | execute(&Body::add_force, this); 56 | } 57 | 58 | void reset_force() { 59 | force_[0] = 0; 60 | force_[1] = 0; 61 | } 62 | 63 | void update(double dt) { 64 | velocity_[0] += force_[0]*dt / mass_; 65 | velocity_[1] += force_[1]*dt / mass_; 66 | position_[0] += velocity_[0]*dt; 67 | position_[1] += velocity_[1]*dt; 68 | 69 | // Reflect bodies. 70 | if (position_[0] < -1 || position_[0] > 1) velocity_[0] = -velocity_[0]; 71 | if (position_[1] < -1 || position_[1] > 1) velocity_[1] = -velocity_[1]; 72 | } 73 | }; 74 | IKRA_HOST_STORAGE(Body) 75 | 76 | int main() { 77 | // Initialize object storage. 78 | Body::initialize_storage(); 79 | 80 | // Create objects. 81 | for (int i = 0; i < kNumBodies; ++i) { 82 | double mass = (RAND/2 + 0.5) * kMaxMass; 83 | double pos_x = RAND*2 - 1; 84 | double pos_y = RAND*2 - 1; 85 | double vel_x = (RAND - 0.5) / 1000; 86 | double vel_y = (RAND - 0.5) / 1000; 87 | new Body(mass, pos_x, pos_y, vel_x, vel_y); 88 | } 89 | 90 | // Run simulation. 91 | for (int i = 0; i < kIterations; ++i) { 92 | // Reset forces. 93 | execute(&Body::reset_force); 94 | 95 | // Update forces. 96 | execute(&Body::add_force_to_all); 97 | 98 | // Update velocities and positions. 99 | execute(&Body::update, kTimeInterval); 100 | } 101 | 102 | return 0; 103 | } 104 | ``` 105 | 106 | ## Installation 107 | ### Prerequisites 108 | * gcc version 5.4.0 or higher 109 | * For visual examples (n-body simulation): SDL 2.0 110 | * For GPU support: CUDA Toolkit 9.0 or higher 111 | * C++11 compiler support in CPU mode, C++14 compiler support in GPU mode 112 | 113 | ### Installation via Git 114 | ``` sh 115 | git clone --recursive git@github.com:prg-titech/ikra-cpp.git 116 | cmake CMakeLists.txt 117 | make 118 | # Check if everything is working. 119 | ctest 120 | bin/n_body 121 | ``` 122 | 123 | -------------------------------------------------------------------------------- /data/bfs/simple.txt: -------------------------------------------------------------------------------- 1 | 0 1 2 | 0 2 3 | 1 0 4 | 2 0 5 | 2 3 6 | 2 5 7 | 3 2 8 | 3 4 9 | 3 7 10 | 3 8 11 | 4 3 12 | 5 2 13 | 5 8 14 | 5 6 15 | 6 5 16 | 6 7 17 | 7 4 18 | 7 6 19 | 8 3 20 | 8 5 21 | -------------------------------------------------------------------------------- /example/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | find_package(SDL2 REQUIRED) 2 | include_directories(${SDL2_INCLUDE_DIRS}) 3 | string(STRIP "${SDL2_LIBRARIES}" SDL2_LIBRARIES) 4 | 5 | add_executable(particle_simulation particle_simulation.cc) 6 | target_link_libraries(particle_simulation ikra ${SDL2_LIBRARIES}) 7 | 8 | add_executable(n_body n_body.cc) 9 | target_link_libraries(n_body ikra ${SDL2_LIBRARIES}) 10 | 11 | add_subdirectory(bfs) 12 | 13 | add_subdirectory(traffic) 14 | -------------------------------------------------------------------------------- /example/bfs/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_executable(bfs_const_size_array bfs_const_size_array.cc) 2 | target_link_libraries(bfs_const_size_array ikra) 3 | 4 | add_executable(bfs_inlined_dynamic_array bfs_inlined_dynamic_array.cc) 5 | target_link_libraries(bfs_inlined_dynamic_array ikra) 6 | 7 | add_executable(bfs_std_vector bfs_std_vector.cc) 8 | target_link_libraries(bfs_std_vector ikra) 9 | 10 | 11 | # CUDA 12 | # TODO: cuda_add_library does not support INTERFACE libraries 13 | include_directories(${CMAKE_SOURCE_DIR}/ikra) 14 | cuda_add_executable(bfs_const_size_array_cuda bfs_const_size_array.cu) 15 | target_link_libraries(bfs_const_size_array_cuda ikra) 16 | -------------------------------------------------------------------------------- /example/bfs/bfs_const_size_array.cc: -------------------------------------------------------------------------------- 1 | #include