Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add python generator script for project templates #669

Open
wants to merge 8 commits into
base: branch-24.03
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion MANIFEST.in
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
include versioneer.py
include legate/_version.py
include legate/py.typed
include legate/cpp_source_template
include legate/cpp_header_template
include legate/python_template

# include interface files
recursive-include legate *.pyi
recursive-include legate *.pyi
26 changes: 25 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -417,6 +417,30 @@ Memory:
Registered CPU-side pinned memory per rank (in MBs) : 0
```

## Getting Your Own Legate Project Started


### Hello World

For basic code examples illustrating how Legate tasks are created
and enqueued, users can look at the [hello world](examples/hello/README.md) example.
The folder includes both a basic "Hello World" as well numerical
examples like variance showing both elementwise array operations
and distributed reductions.

### Library Template

To bootstrap your own Legate library, the `legate-create-library` script
can be used to generate both the build system and initial set of
C++ and Python files.

```bash
$ legate-create-library myproject
$ ls myproject
CMakeLists.txt editable-install.sh install.sh myproject setup.py src
```


## Other FAQs

* *Does Legate only work on NVIDIA hardware?*
Expand Down Expand Up @@ -465,7 +489,7 @@ See the discussion of contributing in [CONTRIBUTING.md](CONTRIBUTING.md).

## Documentation

A complete list of available features can is found in the [Legate Core
A complete list of available features can be found in the [Legate Core
documentation](https://nv-legate.github.io/legate.core).

## Next Steps
Expand Down
194 changes: 24 additions & 170 deletions cmake/legate_helper_functions.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -278,99 +278,10 @@ function(legate_add_cpp_subdirectory dir)
endfunction()

function(legate_cpp_library_template target output_sources_variable)
set(file_template
[=[
/* Copyright 2023 NVIDIA Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

#pragma once

#include "legate.h"

namespace @target@ {

struct Registry {
static legate::TaskRegistrar& get_registrar();
};

template <typename T, int ID>
struct Task : public legate::LegateTask<T> {
using Registrar = Registry;
static constexpr int TASK_ID = ID;
};

}
]=])
string(CONFIGURE "${file_template}" file_content @ONLY)
string(CONFIGURE "${Legate_CPP_HEADER_TEMPLATE}" file_content @ONLY)
file(WRITE ${CMAKE_CURRENT_SOURCE_DIR}/legate_library.h "${file_content}")

set(file_template
[=[
/* Copyright 2023 NVIDIA Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

#include "legate_library.h"

namespace @target@ {

static const char* const library_name = "@target@";

Legion::Logger log_@target@(library_name);

/*static*/ legate::TaskRegistrar& Registry::get_registrar()
{
static legate::TaskRegistrar registrar;
return registrar;
}

void registration_callback()
{
auto context = legate::Runtime::get_runtime()->create_library(library_name);

Registry::get_registrar().register_all_tasks(context);
}

} // namespace @target@

extern "C" {

void @target@_perform_registration(void)
{
// Tell the runtime about our registration callback so we hook it
// in before the runtime starts and make it global so that we know
// that this call back is invoked everywhere across all nodes
legate::Core::perform_registration<@target@::registration_callback>();
}

}
]=])
string(CONFIGURE "${file_template}" file_content @ONLY)
string(CONFIGURE "${Legate_CPP_SOURCE_TEMPLATE}" file_content @ONLY)
file(WRITE ${CMAKE_CURRENT_SOURCE_DIR}/legate_library.cc "${file_content}")

set(${output_sources_variable}
Expand All @@ -381,88 +292,31 @@ void @target@_perform_registration(void)
endfunction()

function(legate_python_library_template py_path)
set(options)
set(one_value_args TARGET PY_IMPORT_PATH)
set(multi_value_args)
cmake_parse_arguments(
LEGATE_OPT
"${options}"
"${one_value_args}"
"${multi_value_args}"
${ARGN}
)

if (DEFINED LEGATE_OPT_TARGET)
set(target "${LEGATE_OPT_TARGET}")
else()
string(REPLACE "/" "_" target "${py_path}")
endif()

if (DEFINED LEGATE_OPT_PY_IMPORT_PATH)
set(py_import_path "${LEGATE_OPT_PY_IMPORT_PATH}")
else()
string(REPLACE "/" "." py_import_path "${py_path}")
endif()

set(fn_library "${CMAKE_CURRENT_SOURCE_DIR}/${py_path}/library.py")

set(file_template
[=[
# Copyright 2023 NVIDIA Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

from legate.core import (
Library,
get_legate_runtime,
)
import os
from typing import Any

class UserLibrary(Library):
def __init__(self, name: str) -> None:
self.name = name
self.shared_object: Any = None

@property
def cffi(self) -> Any:
return self.shared_object

def get_name(self) -> str:
return self.name

def get_shared_library(self) -> str:
from @[email protected]_info import libpath
return os.path.join(libpath, f"lib@target@{self.get_library_extension()}")

def get_c_header(self) -> str:
from @[email protected]_info import header

return header
set(options)
set(one_value_args TARGET PY_IMPORT_PATH)
set(multi_value_args)
cmake_parse_arguments(
LEGATE_OPT
"${options}"
"${one_value_args}"
"${multi_value_args}"
${ARGN}
)

def get_registration_callback(self) -> str:
return "@target@_perform_registration"
if (DEFINED LEGATE_OPT_TARGET)
set(target "${LEGATE_OPT_TARGET}")
else()
string(REPLACE "/" "_" target "${py_path}")
endif()

def initialize(self, shared_object: Any) -> None:
self.shared_object = shared_object
if (DEFINED LEGATE_OPT_PY_IMPORT_PATH)
set(py_import_path "${LEGATE_OPT_PY_IMPORT_PATH}")
else()
string(REPLACE "/" "." py_import_path "${py_path}")
endif()

def destroy(self) -> None:
pass
set(fn_library "${CMAKE_CURRENT_SOURCE_DIR}/${py_path}/library.py")

user_lib = UserLibrary("@target@")
user_context = get_legate_runtime().register_library(user_lib)
]=])
string(CONFIGURE "${file_template}" file_content @ONLY)
string(CONFIGURE "${Legate_PYTHON_TEMPLATE}" file_content @ONLY)
file(WRITE "${fn_library}" "${file_content}")
endfunction()
3 changes: 2 additions & 1 deletion examples/io/src/read_file.cc
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@ struct read_fn {
// Compute the absolute offsets to the section that this reader task
// is supposed to read from the file
int64_t my_lo = my_id * size / num_readers;
int64_t my_hi = std::min((my_id + 1) * size / num_readers, size);
// force min comparison in int64_t
int64_t my_hi = std::min<int64_t>((my_id + 1) * size / num_readers, size);

// Then compute the extent for the output and create the output buffer to populate
int64_t my_ext = my_hi - my_lo;
Expand Down
Loading