From 44d204c6081a4eb574d423f3b716b9d24b9c597c Mon Sep 17 00:00:00 2001 From: Elliott Slaughter Date: Sun, 31 Mar 2024 17:30:07 -0700 Subject: [PATCH] Initial work on adversarial mapper. --- src/CMakeLists.txt | 1 + src/fuzzer.cc | 33 +++++++++--- src/hasher.inl | 10 ++-- src/mapper.cc | 132 +++++++++++++++++++++++++++++++++++++++++++++ src/mapper.h | 67 +++++++++++++++++++++++ 5 files changed, 234 insertions(+), 9 deletions(-) create mode 100644 src/mapper.cc create mode 100644 src/mapper.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index b72fb45..f74d38e 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -2,6 +2,7 @@ add_executable(fuzzer deterministic_random.h deterministic_random.cc deterministic_random.inl fuzzer.cc hasher.h hasher.cc hasher.inl + mapper.h mapper.cc siphash.h siphash.c) target_link_libraries(fuzzer Legion::Legion) set_target_properties(fuzzer PROPERTIES CXX_STANDARD 17) diff --git a/src/fuzzer.cc b/src/fuzzer.cc index 6284de9..561abef 100644 --- a/src/fuzzer.cc +++ b/src/fuzzer.cc @@ -20,6 +20,7 @@ #include "deterministic_random.h" #include "legion.h" +#include "mapper.h" using namespace Legion; @@ -975,14 +976,15 @@ class OperationBuilder { } public: - void execute(Runtime *runtime, Context ctx, std::vector &futures) { + void execute(Runtime *runtime, Context ctx, uint64_t op_idx, + std::vector &futures) { display(runtime, ctx); switch (launch_type) { case LaunchType::SINGLE_TASK: { - execute_single_task(runtime, ctx, futures); + execute_single_task(runtime, ctx, op_idx, futures); } break; case LaunchType::INDEX_TASK: { - execute_index_task(runtime, ctx, futures); + execute_index_task(runtime, ctx, op_idx, futures); } break; default: abort(); @@ -1020,11 +1022,13 @@ class OperationBuilder { } } - void execute_index_task(Runtime *runtime, Context ctx, + void execute_index_task(Runtime *runtime, Context ctx, uint64_t op_idx, std::vector &futures) { PointTaskArgs args(task_arg_value); IndexTaskLauncher launcher(task_id, launch_domain, TaskArgument(&args, sizeof(args)), ArgumentMap()); + static_assert(sizeof(MappingTagID) == sizeof(unsigned long)); + launcher.tag = op_idx & ULONG_MAX; req.add_to_index_task(launcher); if (elide_future_return) { launcher.elide_future_return = true; @@ -1054,11 +1058,13 @@ class OperationBuilder { } } - void execute_single_task(Runtime *runtime, Context ctx, + void execute_single_task(Runtime *runtime, Context ctx, uint64_t op_idx, std::vector &futures) { for (uint64_t point = range_min; point <= range_max; ++point) { 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.point = Point<1>((point - range_min + shard_offset) % range_size + range_min); LOG_ONCE(log_fuzz.info() << " Task: " << point); @@ -1156,7 +1162,7 @@ void top_level(const Task *task, const std::vector ®ions, Con // while skipping operations. if (op_idx >= config.skip_ops) { LOG_ONCE(log_fuzz.info() << "Operation: " << op_idx); - op.execute(runtime, ctx, futures); + op.execute(runtime, ctx, op_idx, futures); } } @@ -1173,6 +1179,19 @@ void top_level(const Task *task, const std::vector ®ions, Con } } +static void create_mappers(Machine machine, Runtime *runtime, + const std::set &local_procs) { + for (Processor proc : local_procs) { + FuzzMapper *mapper = + new FuzzMapper(runtime->get_mapper_runtime(), machine, root_seed.make_stream()); + runtime->replace_default_mapper(mapper, proc); + } +} + +void add_mapper_registration_callback(RngSeed &seed) { + Runtime::add_registration_callback(create_mappers); +} + int main(int argc, char **argv) { Runtime::initialize(&argc, &argv, true /* filter */); FuzzerConfig config = FuzzerConfig::parse_args(argc, argv); @@ -1267,5 +1286,7 @@ int main(int argc, char **argv) { registrar, "uint64_replicable_inner"); } + Runtime::add_registration_callback(create_mappers); + return Runtime::start(argc, argv); } diff --git a/src/hasher.inl b/src/hasher.inl index 1e90cb2..7ca9f7a 100644 --- a/src/hasher.inl +++ b/src/hasher.inl @@ -14,8 +14,10 @@ */ enum HashTypeTag { + INT_TYPE_ID, LONG_LONG_TYPE_ID, - INT32_T_TYPE_ID, + // Clang thinks this is the same as int, so we don't get to have nice things + // 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, @@ -79,8 +81,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(uint64_t, UINT64_T_TYPE_ID) @@ -125,8 +128,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(uint64_t) diff --git a/src/mapper.cc b/src/mapper.cc new file mode 100644 index 0000000..004ff31 --- /dev/null +++ b/src/mapper.cc @@ -0,0 +1,132 @@ +/* Copyright 2024 Stanford University + * + * 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 "mapper.h" + +using namespace Legion; +using namespace Legion::Mapping; + +enum MapperCallIDs { + SELECT_TASKS_TO_MAP, + MAP_TASK, +}; + +static Logger log_map("fuzz_mapper"); + +FuzzMapper::FuzzMapper(MapperRuntime* rt, Machine machine, RngStream st) + : NullMapper(rt, machine), + stream(st), + select_tasks_to_map_channel(st.make_channel(int(SELECT_TASKS_TO_MAP))) {} + +const char* FuzzMapper::get_mapper_name(void) const { return "fuzz_mapper"; } + +Mapper::MapperSyncModel FuzzMapper::get_mapper_sync_model(void) const { + return SERIALIZED_REENTRANT_MAPPER_MODEL; +} + +void FuzzMapper::select_task_options(const MapperContext ctx, const Task& task, + Mapper::TaskOptions& output) { + // output.initial_proc = local_proc; // Leave the task where it is. + output.inline_task = false; + output.stealable = false; + output.map_locally = false; // TODO + output.valid_instances = false; + output.memoize = true; + output.replicate = true; + // output.parent_priority = ...; // Leave parent at current priority. + // output.check_collective_regions.insert(...); // TODO +} + +void FuzzMapper::replicate_task(MapperContext ctx, const Task& task, + const ReplicateTaskInput& input, + ReplicateTaskOutput& output) { + // TODO: cache this? + std::vector variants; + runtime->find_valid_variants(ctx, task.task_id, variants); + if (variants.size() != 1) { + log_map.fatal() << "Bad variants in replicate_task: " << variants.size() + << ", expected: 1"; + abort(); + } + output.chosen_variant = variants.at(0); + // TODO: actually replicate +} + +void FuzzMapper::map_task(const MapperContext ctx, const Task& task, + const MapTaskInput& input, MapTaskOutput& output) { + // RngChannel rng = make_task_channel(MAP_TASK, task); + + // TODO: cache this? + std::vector variants; + runtime->find_valid_variants(ctx, task.task_id, variants); + if (variants.size() != 1) { + log_map.fatal() << "Bad variants in map_task: " << variants.size() << ", expected: 1"; + abort(); + } + output.chosen_variant = variants.at(0); + + // 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()); +} + +void FuzzMapper::select_partition_projection(const MapperContext ctx, + const Partition& partition, + const SelectPartitionProjectionInput& input, + SelectPartitionProjectionOutput& output) { + if (!input.open_complete_partitions.empty()) + output.chosen_partition = input.open_complete_partitions.at(0); + else + output.chosen_partition = LogicalPartition::NO_PART; +} + +void FuzzMapper::configure_context(const MapperContext ctx, const Task& task, + ContextConfigOutput& output) {} + +void FuzzMapper::select_tasks_to_map(const MapperContext ctx, + const SelectMappingInput& input, + SelectMappingOutput& output) { + // 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()); + 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; + } + if (it == input.ready_tasks.end()) { + log_map.fatal() << "Out of bounds in select_tasks_to_map"; + abort(); + } + output.map_tasks.insert(*it); +} + +void FuzzMapper::select_steal_targets(const MapperContext ctx, + const SelectStealingInput& input, + SelectStealingOutput& output) {} + +RngChannel FuzzMapper::make_task_channel(int mapper_call, + const Legion::Task& task) const { + // TODO: index launches, mapper call ID + static_assert(sizeof(MappingTagID) <= sizeof(uint64_t)); + return stream.make_channel(std::pair(mapper_call, uint64_t(task.tag))); +} diff --git a/src/mapper.h b/src/mapper.h new file mode 100644 index 0000000..21e1f40 --- /dev/null +++ b/src/mapper.h @@ -0,0 +1,67 @@ +/* Copyright 2024 Stanford University + * + * 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. + */ + +#ifndef MAPPER_H_ +#define MAPPER_H_ + +#include "deterministic_random.h" +#include "legion.h" +#include "null_mapper.h" + +class FuzzMapper : public Legion::Mapping::NullMapper { +public: + FuzzMapper(Legion::Mapping::MapperRuntime* runtime, Legion::Machine machine, + 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, + const ReplicateTaskInput& input, + ReplicateTaskOutput& output) override; + void map_task(const Legion::Mapping::MapperContext ctx, const Legion::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, + 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; + +public: // Mapping control and stealing + void select_tasks_to_map(const Legion::Mapping::MapperContext ctx, + const SelectMappingInput& input, + SelectMappingOutput& output) override; + void select_steal_targets(const Legion::Mapping::MapperContext ctx, + const SelectStealingInput& input, + SelectStealingOutput& output) override; + +private: + RngChannel make_task_channel(int mapper_call, const Legion::Task& task) const; + +private: + RngStream stream; + RngChannel select_tasks_to_map_channel; +}; + +#endif // MAPPER_H_