Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/master'
Browse files Browse the repository at this point in the history
  • Loading branch information
mroethlin committed Jan 23, 2020
2 parents 6550116 + 12aee56 commit d933ffe
Show file tree
Hide file tree
Showing 122 changed files with 3,626 additions and 2,215 deletions.
File renamed without changes.
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,13 +68,13 @@ We introduce a new compiler framework, consisting of GTClang and Dawn, that deco

## Developer Instructions

If you wish to contribute to dawn or gtclang, please fork this repo into your own github user first, then send a pull request using a descriptive branch name from there. Before submitting a PR, please make sure that:
If you wish to contribute to dawn or gtclang, please fork this repo into your own GitHub user space first, then send a pull request using a descriptive branch name from there. Before submitting a PR, please ensure that:

* All tests are passing. This includes the dawn and GTClang unit tests and the tests performed in the dawn install step. In order that the full test suites are performed, gtclang needs to be built with [GridTools](https://github.com/GridTools/gridtools) enabled, and dawn needs to be built with python exampled enabled. Please see the `README.md` in the dawn and gtclang directories respectivley for information on how to do that.
* All tests pass via `ctest`. In order to make sure all tests are built, add `-DBUILD_TESTING=ON -DDAWN_REQUIRE_PYTHON_TESTING=ON` to the CMake configure command.
* The code is properly formatted according to the clang-format rules provided. This can be ensured automatically using the git hook located in scripts. To install it, simply put a symlink into your `.git` directory (usually located in the top level dawn folder, except if using git work trees) to the script as follows:

```bash
$ ln -s $(pwd)/dawn/scripts/git_hooks/pre-commit $(pwd)/.git/hooks/
$ ln -s $(pwd)/scripts/git_hooks/pre-commit $(pwd)/.git/hooks/
```

If you want to call the script manually, simply run `scripts/clang_format_all.sh`.
Expand Down
3 changes: 1 addition & 2 deletions dawn/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -155,8 +155,7 @@ if(Python3_FOUND)
)
endif()
mark_as_advanced(PROTOBUF_PYTHON_DIR)
find_package(PythonLibs REQUIRED)
if(PROTOBUF_PYTHON_DIR AND PYTHONLIBS_FOUND)
if(PROTOBUF_PYTHON_DIR)
set(ENABLE_PYTHON ON)
else()
set(ENABLE_PYTHON OFF)
Expand Down
1 change: 1 addition & 0 deletions dawn/examples/python/data/.clang-format
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
DisableFormat: true
84 changes: 36 additions & 48 deletions dawn/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,22 +24,17 @@


DAWN_DIR = os.path.join(os.path.dirname(__file__))
BUNDLE_PREFIX = "bundle"
BUNDLE_DIR = os.path.join(DAWN_DIR, BUNDLE_PREFIX)
BUNDLE_ABS_DIR = os.path.abspath(BUNDLE_DIR)

DAWN_ABS_DIR = os.path.abspath(DAWN_DIR)
BUILD_JOBS = 4


# Select protobuf version
# TODO: avoid parsing python files and adapt to new CMake
with open(os.path.join(DAWN_DIR, "cmake", "thirdparty", "DawnAddProtobuf.cmake"), "r") as f:
with open(os.path.join(DAWN_DIR, "cmake", "FetchProtobuf.cmake"), "r") as f:
text = f.read()
m = re.search(r"set\(protobuf_version\s+\"([0-9\.]+)\s*\"\)", text)
protobuf_version = m.group(1)

install_requires = ["attrs>=19", "black>=19.3b0", f"protobuf=={protobuf_version}", "pytest>=4.3.0"]
m = re.search(r".*\/protocolbuffers\/protobuf\/archive\/v(?P<version>.*)(?=\.tar)+", text)
protobuf_version = m.group("version")

install_requires = ["attrs>=19", "black>=19.3b0", f"protobuf>={protobuf_version}", "pytest>=4.3.0"]

# Based on:
# https://www.benjack.io/2018/02/02/python-cpp-revisited.html
Expand All @@ -54,65 +49,59 @@ def run(self):
assert all(isinstance(ext, CMakeExtension) for ext in self.extensions)

# Check if a recent version of CMake is present
cmake_executable = os.getenv("CMAKE_EXECUTABLE", default="cmake")
cmake_args = os.getenv("CMAKE_ARGS", default="").split(" ") or []
try:
out = subprocess.check_output(["cmake", "--version"])
out = subprocess.check_output([cmake_executable, "--version"])
except OSError:
raise RuntimeError(
"CMake must be installed to build the following extensions: "
+ ", ".join(e.name for e in self.extensions)
)

cmake_version = LooseVersion(re.search(r"version\s*([\d.]+)", out.decode()).group(1))
if cmake_version < "3.12.0":
raise RuntimeError("CMake >= 3.12.0 is required")
if cmake_version < "3.13.0":
raise RuntimeError("CMake >= 3.13.0 is required")

# Set build folder inside bundle and remove CMake cache if it contains wrong paths.
# build here
self.build_temp = os.path.join(DAWN_DIR, "build")

# Set build folder inside dawn and remove CMake cache if it contains wrong paths.
# Installing in editable/develop mode builds the extension in the original build path,
# but a regular `pip install` copies the full tree to a temporary folder
# before building, which makes CMake fail if a CMake cache had been already generated.
self.bundle_build_temp = str(os.path.join(BUNDLE_ABS_DIR, "build"))
cmake_cache_file = os.path.join(self.bundle_build_temp, "CMakeCache.txt")
cmake_cache_file = os.path.join(self.build_temp, "CMakeCache.txt")
if os.path.exists(cmake_cache_file):
with open(cmake_cache_file, "r") as f:
text = f.read()
m = re.search(r"\s*dawn_BINARY_DIR\s*:\s*STATIC\s*=\s*([\w/\\]+)\s*", text)
m = re.search(r"\s*Dawn_BINARY_DIR\s*:\s*STATIC\s*=\s*([\w/\\]+)\s*", text)
cache_build_dir = m.group(1) if m else ""
if str(self.bundle_build_temp) != cache_build_dir:
shutil.rmtree(self.bundle_build_temp, ignore_errors=False)
shutil.rmtree(os.path.join(BUNDLE_ABS_DIR, "install"), ignore_errors=True)
if str(self.build_temp) != cache_build_dir:
shutil.rmtree(self.build_temp, ignore_errors=False)
shutil.rmtree(os.path.join(DAWN_DIR, "install"), ignore_errors=True)
assert not os.path.exists(cmake_cache_file)
os.makedirs(self.bundle_build_temp, exist_ok=True)
os.makedirs(self.build_temp, exist_ok=True)
os.makedirs(os.path.join(DAWN_DIR, "install"), exist_ok=True)

# Prepare cmake environment and args
env = os.environ.copy()
env["CXXFLAGS"] = '{} -DVERSION_INFO=\\"{}\\"'.format(
env.get("CXXFLAGS", ""), self.distribution.get_version()
)

cmake_args = [
"-DPYTHON_EXECUTABLE=" + sys.executable,
"-DUSE_SYSTEM_DAWN=False",
"-DUSE_SYSTEM_PROTOBUF=False",
"-DDAWN_BUNDLE_PYTHON=True",
"-DBUILD_TESTING=False",
]
# Prepare CMake arguments
cmake_args += ["-DPYTHON_EXECUTABLE=" + sys.executable, "-DBUILD_TESTING=False"]

cfg = "Debug" if self.debug else "Release"
cmake_args += ["-DCMAKE_BUILD_TYPE=" + cfg]

# Run CMake configure
print("-" * 10, "Running CMake prepare", "-" * 40)
cmake_cmd = ["cmake", BUNDLE_ABS_DIR] + cmake_args
print("{cwd} $ {cmd}".format(cwd=self.bundle_build_temp, cmd=" ".join(cmake_cmd)))
subprocess.check_call(cmake_cmd, cwd=self.bundle_build_temp, env=env)
cmake_cmd = ["cmake", "-S", DAWN_ABS_DIR, "-B", self.build_temp] + cmake_args
print("{cwd} $ {cmd}".format(cwd=self.build_temp, cmd=" ".join(cmake_cmd)))
subprocess.check_call(cmake_cmd)

# Run CMake build
# TODO: run build for the target with the extension name for each extension in self.extensions
print("-" * 10, "Building extensions", "-" * 40)
build_args = ["--config", cfg, "-j", str(BUILD_JOBS), "--target", "dawn"]
cmake_cmd = ["cmake", "--build", "."] + build_args
print("{cwd} $ {cmd}".format(cwd=self.bundle_build_temp, cmd=" ".join(cmake_cmd)))
subprocess.check_call(cmake_cmd, cwd=self.bundle_build_temp)
build_args = ["--config", cfg, "-j", str(BUILD_JOBS)]
cmake_cmd = ["cmake", "--build", self.build_temp, "--target", "python"] + build_args
print("{cwd} $ {cmd}".format(cwd=self.build_temp, cmd=" ".join(cmake_cmd)))
subprocess.check_call(cmake_cmd)

# Move from build temp to final position
for ext in self.extensions:
Expand All @@ -124,11 +113,7 @@ def run(self):
def build_extension(self, ext):
# Currently just copy the generated CPython extension to the package folder
filename = self.get_ext_filename(ext.name)
source_path = os.path.abspath(
os.path.join(
self.bundle_build_temp, "dawn-prefix", "src", "dawn-build", "src", filename
)
)
source_path = os.path.abspath(os.path.join(self.build_temp, "src", filename))
dest_build_path = os.path.abspath(self.get_ext_fullpath(ext.name))
self.copy_file(source_path, dest_build_path)

Expand Down Expand Up @@ -160,12 +145,15 @@ def run(self):
)


with open(os.path.join(DAWN_DIR, "version.txt"), mode="r") as f:
version = f.read().strip("\n")

setup(
name="dawn4py",
version="0.0.1", # TODO: automatic update of version tag
version=version,
author="MeteoSwiss / ETH Zurich",
author_email="gridtools@cscs.com",
description="High-level DSLs toolchain for geophysical fluid dynamics models",
description="High-level DSL toolchain for geophysical fluid dynamics models",
long_description="",
include_package_data=True,
packages=find_packages("src"),
Expand Down
12 changes: 12 additions & 0 deletions dawn/src/dawn/AST/Offsets.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

#include "Offsets.h"

#include "dawn/Support/Assert.h"
#include "dawn/Support/Unreachable.h"
#include <iostream>

Expand Down Expand Up @@ -118,6 +119,17 @@ HorizontalOffset& HorizontalOffset::operator+=(HorizontalOffset const& other) {
}
bool HorizontalOffset::isZero() const { return !impl_ || impl_->isZero(); }

bool HorizontalOffset::hasType() const { return impl_.get() != nullptr; }

GridType HorizontalOffset::getGridType() const {
DAWN_ASSERT(hasType());
if(dynamic_cast<CartesianOffset*>(impl_.get())) {
return GridType::Cartesian;
} else {
return GridType::Triangular;
}
}

// Offsets

Offsets::Offsets(HorizontalOffset const& hOffset, int vOffset)
Expand Down
6 changes: 6 additions & 0 deletions dawn/src/dawn/AST/Offsets.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#ifndef DAWN_AST_OFFSET_H
#define DAWN_AST_OFFSET_H

#include "dawn/AST/GridType.h"
#include "dawn/AST/Tags.h"
#include "dawn/Support/Unreachable.h"

Expand Down Expand Up @@ -109,6 +110,11 @@ class HorizontalOffset {
friend auto offset_dispatch(HorizontalOffset const& hOffset, CartFn const& cartFn,
UnstructuredFn const& unstructuredFn, ZeroFn const& zeroFn);

// impl may be a null ptr, i.e. HorizontalOffset may be in a uninitialized state and not
// associated with a grid type
bool hasType() const;
GridType getGridType() const;

private:
std::unique_ptr<HorizontalOffsetImpl> impl_;
};
Expand Down
18 changes: 18 additions & 0 deletions dawn/src/dawn/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,27 @@ install(
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
)

# GCC 8, still a common compiler, requires linking to a separate library for std::filesystem support.
# Once that is no longer common we can remove this hack
add_library(cpp_extra_libs INTERFACE)
if (CMAKE_COMPILER_IS_GNUCC AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 9.0)
target_link_libraries(cpp_extra_libs INTERFACE stdc++fs)
endif()

install(
TARGETS cpp_extra_libs
EXPORT ${PROJECT_NAME}Targets
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
)

function(add_dawn_library)
foreach(_l IN LISTS ARGN)
# Link to cpp_extra_libs -- see above
target_link_libraries(${_l} PUBLIC cpp_extra_libs)
# Add to main project interface target
target_link_libraries(${PROJECT_NAME} INTERFACE ${_l})
# Add to install target group
install(
TARGETS ${_l}
EXPORT ${PROJECT_NAME}Targets
Expand Down
36 changes: 3 additions & 33 deletions dawn/src/dawn/CodeGen/CXXNaive/CXXNaiveCodeGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -287,41 +287,11 @@ void CXXNaiveCodeGen::generateStencilClasses(
StencilContext::SC_Stencil);

stencilClass.addComment("Members");
bool iterationSpaceSet = false;
for(auto& stage : iterateIIROver<iir::Stage>(stencil)) {
if(stage->getIterationSpace()[0].has_value()) {
stencilClass.addMember("std::array<int, 2>",
"stage" + std::to_string(stage->getStageID()) + "GlobalIIndices");
iterationSpaceSet = true;
}
if(stage->getIterationSpace()[1].has_value()) {
stencilClass.addMember("std::array<int, 2>",
"stage" + std::to_string(stage->getStageID()) + "GlobalJIndices");
iterationSpaceSet = true;
}
}
bool iterationSpaceSet = hasGlobalIndices(stencil);
if(iterationSpaceSet) {
stencilClass.addMember("std::array<unsigned int, 2>", "globalOffsets");
auto globalOffsetFunc = stencilClass.addMemberFunction("static std::array<unsigned int, 2>",
"computeGlobalOffsets");
globalOffsetFunc.addArg("int rank, const " + c_dgt() + "domain& dom, int xcols, int ycols");
globalOffsetFunc.startBody();
globalOffsetFunc.addStatement("unsigned int rankOnDefaultFace = rank % (xcols * ycols)");
globalOffsetFunc.addStatement("unsigned int row = rankOnDefaultFace / xcols");
globalOffsetFunc.addStatement("unsigned int col = rankOnDefaultFace % ycols");
globalOffsetFunc.addStatement(
"return {col * (dom.isize() - dom.iplus()), row * (dom.jsize() - dom.jplus())}");

globalOffsetFunc.commit();

auto checkOffsetFunc = stencilClass.addMemberFunction("static bool", "checkOffset");
checkOffsetFunc.addArg("unsigned int min");
checkOffsetFunc.addArg("unsigned int max");
checkOffsetFunc.addArg("unsigned int val");
checkOffsetFunc.startBody();
checkOffsetFunc.addStatement("return (min <= val && val < max)");
checkOffsetFunc.commit();
generateGlobalIndices(stencil, stencilClass);
}

stencilClass.addComment("Temporary storages");
addTempStorageTypedef(stencilClass, stencil);

Expand Down
57 changes: 56 additions & 1 deletion dawn/src/dawn/CodeGen/CodeGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

namespace dawn {
namespace codegen {

size_t CodeGen::getVerticalTmpHaloSize(iir::Stencil const& stencil) {
std::optional<iir::Interval> tmpInterval = stencil.getEnclosingIntervalTemporaries();
return tmpInterval ? std::max(tmpInterval->overEnd(), tmpInterval->belowBegin()) : 0;
Expand Down Expand Up @@ -366,5 +365,61 @@ std::string CodeGen::generateFileName(const stencilInstantiationContext& context
return "";
}

bool CodeGen::hasGlobalIndices(
const std::shared_ptr<iir::StencilInstantiation>& stencilInstantiation) const {
for(auto& stencil : stencilInstantiation->getStencils()) {
if(hasGlobalIndices(*stencil)) {
return true;
}
}
return false;
}

bool CodeGen::hasGlobalIndices(const iir::Stencil& stencil) const {
for(auto& stage : iterateIIROver<iir::Stage>(stencil)) {
if(std::any_of(stage->getIterationSpace().cbegin(), stage->getIterationSpace().cend(),
[](const auto& p) -> bool { return p.has_value(); })) {
return true;
}
}
return false;
}

void CodeGen::generateGlobalIndices(const iir::Stencil& stencil, Structure& stencilClass,
bool genCheckOffset) const {
for(auto& stage : iterateIIROver<iir::Stage>(stencil)) {
if(stage->getIterationSpace()[0].has_value()) {
stencilClass.addMember("std::array<int, 2>",
"stage" + std::to_string(stage->getStageID()) + "GlobalIIndices");
}
if(stage->getIterationSpace()[1].has_value()) {
stencilClass.addMember("std::array<int, 2>",
"stage" + std::to_string(stage->getStageID()) + "GlobalJIndices");
}
}

stencilClass.addMember("std::array<unsigned int, 2>", "globalOffsets");
auto globalOffsetFunc =
stencilClass.addMemberFunction("static std::array<unsigned int, 2>", "computeGlobalOffsets");
globalOffsetFunc.addArg("int rank, const " + c_dgt() + "domain& dom, int xcols, int ycols");
globalOffsetFunc.startBody();
globalOffsetFunc.addStatement("unsigned int rankOnDefaultFace = rank % (xcols * ycols)");
globalOffsetFunc.addStatement("unsigned int row = rankOnDefaultFace / xcols");
globalOffsetFunc.addStatement("unsigned int col = rankOnDefaultFace % ycols");
globalOffsetFunc.addStatement(
"return {col * (dom.isize() - dom.iplus()), row * (dom.jsize() - dom.jplus())}");
globalOffsetFunc.commit();

if(genCheckOffset) {
auto checkOffsetFunc = stencilClass.addMemberFunction("static bool", "checkOffset");
checkOffsetFunc.addArg("unsigned int min");
checkOffsetFunc.addArg("unsigned int max");
checkOffsetFunc.addArg("unsigned int val");
checkOffsetFunc.startBody();
checkOffsetFunc.addStatement("return (min <= val && val < max)");
checkOffsetFunc.commit();
}
}

} // namespace codegen
} // namespace dawn
7 changes: 7 additions & 0 deletions dawn/src/dawn/CodeGen/CodeGen.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,13 @@ class CodeGen {

void addMplIfdefs(std::vector<std::string>& ppDefines, int mplContainerMaxSize) const;

bool
hasGlobalIndices(const std::shared_ptr<iir::StencilInstantiation>& stencilInstantiation) const;
bool hasGlobalIndices(const iir::Stencil& stencil) const;

void generateGlobalIndices(const iir::Stencil& stencil, Structure& stencilClass,
bool genCheckOffset = true) const;

const std::string tmpStorageTypename_ = "tmp_storage_t";
const std::string tmpMetadataTypename_ = "tmp_meta_data_t";
const std::string tmpMetadataName_ = "m_tmp_meta_data";
Expand Down
Loading

0 comments on commit d933ffe

Please sign in to comment.