Skip to content

Commit

Permalink
More work on allocating instances.
Browse files Browse the repository at this point in the history
  • Loading branch information
elliottslaughter committed Apr 1, 2024
1 parent 44d204c commit cc05489
Show file tree
Hide file tree
Showing 4 changed files with 193 additions and 56 deletions.
8 changes: 4 additions & 4 deletions src/fuzzer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1028,7 +1028,7 @@ class OperationBuilder {
IndexTaskLauncher launcher(task_id, launch_domain, TaskArgument(&args, sizeof(args)),
ArgumentMap());
static_assert(sizeof(MappingTagID) == sizeof(unsigned long));
launcher.tag = op_idx & ULONG_MAX;
launcher.tag = op_idx;
req.add_to_index_task(launcher);
if (elide_future_return) {
launcher.elide_future_return = true;
Expand Down Expand Up @@ -1064,7 +1064,7 @@ class OperationBuilder {
PointTaskArgs args(task_arg_value);
TaskLauncher launcher(task_id, TaskArgument(&args, sizeof(args)));
static_assert(sizeof(MappingTagID) == sizeof(unsigned long));
launcher.tag = op_idx & ULONG_MAX;
launcher.tag = op_idx;
launcher.point =
Point<1>((point - range_min + shard_offset) % range_size + range_min);
LOG_ONCE(log_fuzz.info() << " Task: " << point);
Expand Down Expand Up @@ -1182,8 +1182,8 @@ void top_level(const Task *task, const std::vector<PhysicalRegion> &regions, Con
static void create_mappers(Machine machine, Runtime *runtime,
const std::set<Processor> &local_procs) {
for (Processor proc : local_procs) {
FuzzMapper *mapper =
new FuzzMapper(runtime->get_mapper_runtime(), machine, root_seed.make_stream());
FuzzMapper::FuzzMapper *mapper = new FuzzMapper::FuzzMapper(
runtime->get_mapper_runtime(), machine, proc, root_seed.make_stream());
runtime->replace_default_mapper(mapper, proc);
}
}
Expand Down
20 changes: 6 additions & 14 deletions src/hasher.inl
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,9 @@
*/

enum HashTypeTag {
INT_TYPE_ID,
LONG_LONG_TYPE_ID,
// Clang thinks this is the same as int, so we don't get to have nice things
// INT32_T_TYPE_ID,
INT32_T_TYPE_ID,
UINT32_T_TYPE_ID,
// Clang thinks this is the same as long long, so we don't get to have nice things
// INT64_T_TYPE_ID,
INT64_T_TYPE_ID,
UINT64_T_TYPE_ID,
STD_PAIR_TYPE_ID,
STD_VECTOR_TYPE_ID,
Expand Down Expand Up @@ -81,11 +77,9 @@ private:
friend class HashTypeTagAdapter; \
};

DECLARE_TYPE_ADAPTER(int, INT_TYPE_ID)
DECLARE_TYPE_ADAPTER(long long, LONG_LONG_TYPE_ID)
// DECLARE_TYPE_ADAPTER(int32_t, INT32_T_TYPE_ID)
DECLARE_TYPE_ADAPTER(int32_t, INT32_T_TYPE_ID)
DECLARE_TYPE_ADAPTER(uint32_t, UINT32_T_TYPE_ID)
// DECLARE_TYPE_ADAPTER(int64_t, INT64_T_TYPE_ID)
DECLARE_TYPE_ADAPTER(int64_t, INT64_T_TYPE_ID)
DECLARE_TYPE_ADAPTER(uint64_t, UINT64_T_TYPE_ID)
DECLARE_TYPE_ADAPTER(Legion::DomainPoint, LEGION_DOMAIN_POINT_TYPE_ID)
DECLARE_TYPE_ADAPTER(Legion::Domain, LEGION_DOMAIN_TYPE_ID)
Expand Down Expand Up @@ -128,11 +122,9 @@ private:
friend class HashValueAdapter; \
};

DECLARE_SIMPLE_VALUE_ADAPTER(int)
DECLARE_SIMPLE_VALUE_ADAPTER(long long)
// DECLARE_SIMPLE_VALUE_ADAPTER(int32_t)
DECLARE_SIMPLE_VALUE_ADAPTER(int32_t)
DECLARE_SIMPLE_VALUE_ADAPTER(uint32_t)
// DECLARE_SIMPLE_VALUE_ADAPTER(int64_t)
DECLARE_SIMPLE_VALUE_ADAPTER(int64_t)
DECLARE_SIMPLE_VALUE_ADAPTER(uint64_t)
#undef DECLARE_SIMPLE_VALUE_ADAPTER

Expand Down
176 changes: 155 additions & 21 deletions src/mapper.cc
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

#include "mapper.h"

namespace FuzzMapper {
using namespace Legion;
using namespace Legion::Mapping;

Expand All @@ -25,10 +26,24 @@ enum MapperCallIDs {

static Logger log_map("fuzz_mapper");

FuzzMapper::FuzzMapper(MapperRuntime* rt, Machine machine, RngStream st)
FuzzMapper::FuzzMapper(MapperRuntime* rt, Machine machine, Processor local, RngStream st)
: NullMapper(rt, machine),
stream(st),
select_tasks_to_map_channel(st.make_channel(int(SELECT_TASKS_TO_MAP))) {}
select_tasks_to_map_channel(st.make_channel(int32_t(SELECT_TASKS_TO_MAP))),
local_proc(local) {
// TODO: something other than CPU processor
{
Machine::ProcessorQuery query(machine);
query.only_kind(Processor::LOC_PROC);
query.local_address_space();
local_procs.insert(local_procs.end(), query.begin(), query.end());
}
{
Machine::ProcessorQuery query(machine);
query.only_kind(Processor::LOC_PROC);
global_procs.insert(global_procs.end(), query.begin(), query.end());
}
}

const char* FuzzMapper::get_mapper_name(void) const { return "fuzz_mapper"; }

Expand Down Expand Up @@ -66,7 +81,9 @@ void FuzzMapper::replicate_task(MapperContext ctx, const Task& task,

void FuzzMapper::map_task(const MapperContext ctx, const Task& task,
const MapTaskInput& input, MapTaskOutput& output) {
// RngChannel rng = make_task_channel(MAP_TASK, task);
RngChannel rng = make_task_channel(MAP_TASK, task);

log_map.debug() << "map_task: Start";

// TODO: cache this?
std::vector<VariantID> variants;
Expand All @@ -76,14 +93,103 @@ void FuzzMapper::map_task(const MapperContext ctx, const Task& task,
abort();
}
output.chosen_variant = variants.at(0);
log_map.debug() << "map_task: Selected variant " << output.chosen_variant;

// TODO: assign to variant's correct processor kind
if (rng.uniform_range(0, 1) == 0) {
log_map.debug() << "map_task: Mapping to all local procs";
output.target_procs.insert(output.target_procs.end(), local_procs.begin(),
local_procs.end());
} else {
log_map.debug() << "map_task: Mapping to current proc";
output.target_procs.push_back(local_proc);
}

if (runtime->is_inner_variant(ctx, task.task_id, output.chosen_variant)) {
// For inner variants we'll always select virtual instances
for (size_t idx = 0; idx < task.regions.size(); ++idx) {
output.chosen_instances.at(idx).push_back(PhysicalInstance::get_virtual_instance());
}
} else {
for (size_t idx = 0; idx < task.regions.size(); ++idx) {
const RegionRequirement& req = task.regions.at(idx);
if (req.privilege == LEGION_NO_ACCESS || req.privilege_fields.empty()) {
continue;
}

// TODO: default mapper does a query for each kind here; there is no way to
// look up a variant's kind
Machine::ProcessorQuery query(machine);
query.only_kind(Processor::LOC_PROC);
query.local_address_space();
// TODO: should we randomize this?
output.target_procs.insert(output.target_procs.end(), query.begin(), query.end());
// Pick the memory this is going into
Machine::MemoryQuery query(machine);
query.only_kind(Memory::SYSTEM_MEM); // FIXME: without this it selects file memory?
query.best_affinity_to(local_proc);
uint64_t target = rng.uniform_range(0, query.count() - 1);
auto it = query.begin();
std::advance(it, target);
Memory memory = *it;
log_map.debug() << "map_task: Selected memory " << memory << " kind "
<< memory.kind() << " for requirement " << idx;

LayoutConstraintSet constraints;
if (req.privilege == LEGION_REDUCE) {
constraints.add_constraint(
SpecializedConstraint(LEGION_AFFINE_REDUCTION_SPECIALIZE, req.redop));
} else {
constraints.add_constraint(SpecializedConstraint());
}

constraints.add_constraint(MemoryConstraint(memory.kind()));

{
std::vector<FieldID> fields;
if (rng.uniform_range(0, 1) == 0) {
FieldSpace handle = req.region.get_field_space();
runtime->get_field_space_fields(ctx, handle, fields);
} else {
fields.insert(fields.end(), req.instance_fields.begin(),
req.instance_fields.end());
}
bool contiguous = rng.uniform_range(0, 1) == 0;
bool inorder = rng.uniform_range(0, 1) == 0;

constraints.add_constraint(FieldConstraint(fields, contiguous, inorder));
}

{
IndexSpace is = req.region.get_index_space();
Domain domain = runtime->get_index_space_domain(ctx, is);
int dim = domain.get_dim();
std::vector<DimensionKind> dimension_ordering(dim + 1);
for (int i = 0; i < dim; ++i)
dimension_ordering.at(i) =
static_cast<DimensionKind>(static_cast<int>(LEGION_DIM_X) + i);
dimension_ordering[dim] = LEGION_DIM_F;
// TODO: shuffle this ordering
bool contiguous = rng.uniform_range(0, 1) == 0;
constraints.add_constraint(OrderingConstraint(dimension_ordering, contiguous));
}

std::vector<LogicalRegion> regions = {req.region};

// Either force the runtime to create a fresh instance, or allow one to be reused
PhysicalInstance instance;
if (rng.uniform_range(0, 1) == 0) {
if (!runtime->create_physical_instance(ctx, memory, constraints, regions,
instance, true /* acquire */,
LEGION_GC_MAX_PRIORITY)) {
log_map.fatal() << "map_task: Failed to create instance";
abort();
}
} else {
bool created;
if (!runtime->find_or_create_physical_instance(
ctx, memory, constraints, regions, instance, created, true /* acquire */,
LEGION_GC_NEVER_PRIORITY)) {
log_map.fatal() << "map_task: Failed to create instance";
abort();
}
}
output.chosen_instances.at(idx).push_back(instance);
}
}
}

void FuzzMapper::select_partition_projection(const MapperContext ctx,
Expand All @@ -102,22 +208,40 @@ void FuzzMapper::configure_context(const MapperContext ctx, const Task& task,
void FuzzMapper::select_tasks_to_map(const MapperContext ctx,
const SelectMappingInput& input,
SelectMappingOutput& output) {
RngChannel& rng = select_tasks_to_map_channel;

log_map.debug() << "select_tasks_to_map: Start";
if (input.ready_tasks.empty()) {
log_map.fatal() << "select_tasks_to_map: Empty ready list";
abort();
}

// Just to really mess with things, we'll pick a random task on every invokation.
uint64_t target =
select_tasks_to_map_channel.uniform_range(0, input.ready_tasks.size());
uint64_t target = rng.uniform_range(0, input.ready_tasks.size());
log_map.debug() << "select_tasks_to_map: Selected task " << target << " of "
<< input.ready_tasks.size();
auto it = input.ready_tasks.begin();
for (uint64_t idx = 0; idx < target; ++idx) {
if (it == input.ready_tasks.end()) {
log_map.fatal() << "Out of bounds in select_tasks_to_map";
abort();
}
++it;
}
std::advance(it, target);
if (it == input.ready_tasks.end()) {
log_map.fatal() << "Out of bounds in select_tasks_to_map";
log_map.fatal() << "select_tasks_to_map: Out of bounds ";
abort();
}
output.map_tasks.insert(*it);

// What to do? Map it here, or send it elsewhere?
switch (rng.uniform_range(0, 3)) {
case 0:
case 1: {
output.map_tasks.insert(*it);
} break;
case 2: {
output.relocate_tasks[*it] = random_local_proc(rng);
} break;
case 3: {
output.relocate_tasks[*it] = random_global_proc(rng);
} break;
default:
abort();
}
}

void FuzzMapper::select_steal_targets(const MapperContext ctx,
Expand All @@ -130,3 +254,13 @@ RngChannel FuzzMapper::make_task_channel(int mapper_call,
static_assert(sizeof(MappingTagID) <= sizeof(uint64_t));
return stream.make_channel(std::pair(mapper_call, uint64_t(task.tag)));
}

Processor FuzzMapper::random_local_proc(RngChannel& rng) {
return local_procs.at(rng.uniform_range(0, local_procs.size() - 1));
}

Processor FuzzMapper::random_global_proc(RngChannel& rng) {
return global_procs.at(rng.uniform_range(0, global_procs.size() - 1));
}

} // namespace FuzzMapper
45 changes: 28 additions & 17 deletions src/mapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,48 +20,59 @@
#include "legion.h"
#include "null_mapper.h"

class FuzzMapper : public Legion::Mapping::NullMapper {
namespace FuzzMapper {
// Because C++ won't let us put this in the class, we have to create an
// entire namespace to scope these
using namespace Legion;
using namespace Legion::Mapping;

class FuzzMapper : public NullMapper {
public:
FuzzMapper(Legion::Mapping::MapperRuntime* runtime, Legion::Machine machine,
RngStream stream);
FuzzMapper(MapperRuntime* runtime, Machine machine, Processor local, RngStream stream);

public:
const char* get_mapper_name(void) const override;
MapperSyncModel get_mapper_sync_model(void) const override;

public: // Task mapping calls
void select_task_options(const Legion::Mapping::MapperContext ctx,
const Legion::Task& task, TaskOptions& output) override;
void replicate_task(Legion::Mapping::MapperContext ctx, const Legion::Task& task,
void select_task_options(const MapperContext ctx, const Task& task,
TaskOptions& output) override;
void replicate_task(MapperContext ctx, const Task& task,
const ReplicateTaskInput& input,
ReplicateTaskOutput& output) override;
void map_task(const Legion::Mapping::MapperContext ctx, const Legion::Task& task,
const MapTaskInput& input, MapTaskOutput& output) override;
void map_task(const MapperContext ctx, const Task& task, const MapTaskInput& input,
MapTaskOutput& output) override;

public: // Partition mapping calls
void select_partition_projection(const Legion::Mapping::MapperContext ctx,
const Legion::Partition& partition,
void select_partition_projection(const MapperContext ctx, const Partition& partition,
const SelectPartitionProjectionInput& input,
SelectPartitionProjectionOutput& output) override;

public: // Task execution mapping calls
void configure_context(const Legion::Mapping::MapperContext ctx,
const Legion::Task& task, ContextConfigOutput& output) override;
void configure_context(const MapperContext ctx, const Task& task,
ContextConfigOutput& output) override;

public: // Mapping control and stealing
void select_tasks_to_map(const Legion::Mapping::MapperContext ctx,
const SelectMappingInput& input,
void select_tasks_to_map(const MapperContext ctx, const SelectMappingInput& input,
SelectMappingOutput& output) override;
void select_steal_targets(const Legion::Mapping::MapperContext ctx,
const SelectStealingInput& input,
void select_steal_targets(const MapperContext ctx, const SelectStealingInput& input,
SelectStealingOutput& output) override;

private:
RngChannel make_task_channel(int mapper_call, const Legion::Task& task) const;
RngChannel make_task_channel(int mapper_call, const Task& task) const;

Processor random_local_proc(RngChannel& rng);
Processor random_global_proc(RngChannel& rng);

private:
RngStream stream;
RngChannel select_tasks_to_map_channel;

Processor local_proc;
std::vector<Processor> local_procs;
std::vector<Processor> global_procs;
};

} // namespace FuzzMapper

#endif // MAPPER_H_

0 comments on commit cc05489

Please sign in to comment.