Skip to content

Instantly share code, notes, and snippets.

@dotnwat
Last active August 29, 2015 14:22
Show Gist options
  • Save dotnwat/8c514ec5fa3d23de4523 to your computer and use it in GitHub Desktop.
Save dotnwat/8c514ec5fa3d23de4523 to your computer and use it in GitHub Desktop.
Summation in Legion
/*
* Single task, one mapping.
*/
#include "legion.h"
using namespace LegionRuntime::HighLevel;
using namespace LegionRuntime::Accessor;
enum TaskIDs {
TOP_LEVEL_TASK_ID,
};
enum FieldIDs {
FID_VALUE,
};
void top_level_task(const Task *task,
const std::vector<PhysicalRegion> &regions,
Context ctx, HighLevelRuntime *runtime)
{
/* size of sequence 1..num_elements */
int num_elements = 1024;
/*
* Setup the logical region
*/
Rect<1> elem_rect(Point<1>(0),Point<1>(num_elements-1));
IndexSpace is = runtime->create_index_space(ctx,
Domain::from_rect<1>(elem_rect));
FieldSpace fs = runtime->create_field_space(ctx);
{
FieldAllocator allocator = runtime->create_field_allocator(ctx, fs);
allocator.allocate_field(sizeof(uint64_t), FID_VALUE);
}
LogicalRegion lr = runtime->create_logical_region(ctx, is, fs);
/*
* Map the region
*/
RegionRequirement req(lr, READ_WRITE, EXCLUSIVE, lr);
req.add_field(FID_VALUE);
InlineLauncher fill_launcher(req);
PhysicalRegion region = runtime->map_region(ctx, fill_launcher);
region.wait_until_valid();
/*
* Write values into region
*/
RegionAccessor<AccessorType::Generic, uint64_t> acc =
region.get_field_accessor(FID_VALUE).typeify<uint64_t>();
uint64_t value = 0;
for (GenericPointInRectIterator<1> pir(elem_rect); pir; pir++)
{
value++;
acc.write(DomainPoint::from_point<1>(pir.p), value);
}
/*
* Perform summation
*/
RegionAccessor<AccessorType::Generic, uint64_t> acc_read =
region.get_field_accessor(FID_VALUE).typeify<uint64_t>();
uint64_t sum = 0;
for (GenericPointInRectIterator<1> pir(elem_rect); pir; pir++)
{
sum += acc_read.read(DomainPoint::from_point<1>(pir.p));
}
/* Verify */
assert(sum == ((value * (value + 1)) / 2));
}
int main(int argc, char **argv)
{
HighLevelRuntime::set_top_level_task_id(TOP_LEVEL_TASK_ID);
HighLevelRuntime::register_legion_task<top_level_task>(TOP_LEVEL_TASK_ID,
Processor::LOC_PROC, true/*single*/, false/*index*/);
return HighLevelRuntime::start(argc, argv);
}
/*
* - Index space launch to fill region
* - Index space launch to compute per-region summation
* - Reduction over FutureMap for final global summation
*/
#include "legion.h"
using namespace LegionRuntime::HighLevel;
using namespace LegionRuntime::Accessor;
enum TaskIDs {
TOP_LEVEL_TASK_ID,
FILL_TASK_ID,
SUM_TASK_ID,
};
enum FieldIDs {
FID_VALUE,
};
enum RedopIDs {
ADD_REDOP_ID = 1,
};
struct AddRedop {
typedef uint64_t LHS;
typedef uint64_t RHS;
static const uint64_t identity;
template <bool EXCLUSIVE>
static void apply(LHS& lhs, RHS rhs);
template <bool EXCLUSIVE>
static void fold(RHS& rhs1, RHS rhs2);
};
const uint64_t AddRedop::identity = 0;
template<>
void AddRedop::apply<true>(LHS& lhs, RHS rhs)
{
lhs += rhs;
}
template<>
void AddRedop::apply<false>(LHS& lhs, RHS rhs)
{
int64_t *target = (int64_t *)&lhs;
union { int64_t as_int; uint64_t as_T; } oldval, newval;
do {
oldval.as_int = *target;
newval.as_T = oldval.as_T + rhs;
} while (!__sync_bool_compare_and_swap(target, oldval.as_int, newval.as_int));
}
template<>
void AddRedop::fold<true>(RHS& rhs1, RHS rhs2)
{
rhs1 += rhs2;
}
template<>
void AddRedop::fold<false>(RHS &rhs1, RHS rhs2)
{
int64_t *target = (int64_t *)&rhs1;
union { int64_t as_int; uint64_t as_T; } oldval, newval;
do {
oldval.as_int = *target;
newval.as_T = oldval.as_T + rhs2;
} while (!__sync_bool_compare_and_swap(target, oldval.as_int, newval.as_int));
}
void top_level_task(const Task *task,
const std::vector<PhysicalRegion> &regions,
Context ctx, HighLevelRuntime *runtime)
{
/* size of sequence 1..num_elements */
int num_elements = 1024;
/* break problem up into num_subregions */
int num_subregions = 4;
/* assumption makes stuff simpler */
assert(num_elements % num_subregions == 0);
/*
* Setup the logical region
*/
Rect<1> elem_rect(Point<1>(0),Point<1>(num_elements-1));
IndexSpace is = runtime->create_index_space(ctx,
Domain::from_rect<1>(elem_rect));
FieldSpace fs = runtime->create_field_space(ctx);
{
FieldAllocator allocator = runtime->create_field_allocator(ctx, fs);
allocator.allocate_field(sizeof(uint64_t), FID_VALUE);
}
LogicalRegion lr = runtime->create_logical_region(ctx, is, fs);
/*
* Setup a partitioning
*/
Rect<1> color_bounds(Point<1>(0),Point<1>(num_subregions-1));
Domain color_domain = Domain::from_rect<1>(color_bounds);
Blockify<1> coloring(num_elements/num_subregions);
IndexPartition ip = runtime->create_index_partition(ctx, is, coloring);
LogicalPartition lp = runtime->get_logical_partition(ctx, lr, ip);
Domain launch_domain = color_domain;
ArgumentMap arg_map;
/*
* Fill up the logical region
*/
IndexLauncher fill_launcher(FILL_TASK_ID, launch_domain,
TaskArgument(NULL, 0), arg_map);
fill_launcher.add_region_requirement(
RegionRequirement(lp, 0, WRITE_DISCARD, EXCLUSIVE, lr));
fill_launcher.region_requirements[0].add_field(FID_VALUE);
runtime->execute_index_space(ctx, fill_launcher);
/*
* Sum up all the values
*/
IndexLauncher sum_launcher(SUM_TASK_ID, launch_domain,
TaskArgument(NULL, 0), arg_map);
sum_launcher.add_region_requirement(
RegionRequirement(lp, 0, READ_ONLY, EXCLUSIVE, lr));
sum_launcher.region_requirements[0].add_field(FID_VALUE);
Future sumf = runtime->execute_index_space(ctx, sum_launcher, ADD_REDOP_ID);
/* Verify */
uint64_t sum = sumf.get_result<uint64_t>();
assert(sum == ((num_elements * (num_elements - 1)) / 2));
}
void fill_task(const Task *task,
const std::vector<PhysicalRegion> &regions,
Context ctx, HighLevelRuntime *runtime)
{
RegionAccessor<AccessorType::Generic, uint64_t> acc =
regions[0].get_field_accessor(FID_VALUE).typeify<uint64_t>();
Domain dom = runtime->get_index_space_domain(ctx,
task->regions[0].region.get_index_space());
Rect<1> rect = dom.get_rect<1>();
/*
* Write the position as the "value"
*/
for (GenericPointInRectIterator<1> pir(rect); pir; pir++)
{
acc.write(DomainPoint::from_point<1>(pir.p), pir.p[0]);
}
}
uint64_t sum_task(const Task *task,
const std::vector<PhysicalRegion> &regions,
Context ctx, HighLevelRuntime *runtime)
{
RegionAccessor<AccessorType::Generic, uint64_t> acc =
regions[0].get_field_accessor(FID_VALUE).typeify<uint64_t>();
Domain dom = runtime->get_index_space_domain(ctx,
task->regions[0].region.get_index_space());
Rect<1> rect = dom.get_rect<1>();
/*
* Add up all the value in this partition
*/
uint64_t value = 0;
for (GenericPointInRectIterator<1> pir(rect); pir; pir++)
{
value += acc.read(DomainPoint::from_point<1>(pir.p));
}
return value;
}
int main(int argc, char **argv)
{
HighLevelRuntime::set_top_level_task_id(TOP_LEVEL_TASK_ID);
HighLevelRuntime::register_legion_task<top_level_task>(TOP_LEVEL_TASK_ID,
Processor::LOC_PROC, true/*single*/, false/*index*/);
HighLevelRuntime::register_legion_task<fill_task>(FILL_TASK_ID,
Processor::LOC_PROC, true/*single*/, true/*index*/,
AUTO_GENERATE_ID, TaskConfigOptions(true), "fill");
HighLevelRuntime::register_legion_task<uint64_t, sum_task>(SUM_TASK_ID,
Processor::LOC_PROC, true/*single*/, true/*index*/,
AUTO_GENERATE_ID, TaskConfigOptions(true), "sum");
HighLevelRuntime::register_reduction_op<AddRedop>(ADD_REDOP_ID);
return HighLevelRuntime::start(argc, argv);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment