Skip to content

Commit

Permalink
Add randomized projection functor.
Browse files Browse the repository at this point in the history
  • Loading branch information
elliottslaughter committed Mar 31, 2024
1 parent a94dade commit 8f6b307
Show file tree
Hide file tree
Showing 10 changed files with 425 additions and 23 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ PREFIX ?= # Location of where to install Legion
OUTFILE ?= fuzzer
# List all the application source files here
CC_SRC ?= src/siphash.c # .c files
CXX_SRC ?= src/fuzzer.cc src/deterministic_random.cc # .cc files
CXX_SRC ?= src/fuzzer.cc src/deterministic_random.cc src/hasher.cc # .cc files
CUDA_SRC ?= # .cu files
FORT_SRC ?= # .f90 files
HIP_SRC ?= # .cu files
Expand Down
2 changes: 1 addition & 1 deletion format.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

set -e

for f in src/*.h src/*.cc; do
for f in src/*.h src/*.cc src/*.inl; do
clang-format -i "$f" &
done
black . &
Expand Down
3 changes: 2 additions & 1 deletion src/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
add_executable(fuzzer
deterministic_random.h deterministic_random.cc
deterministic_random.h deterministic_random.cc deterministic_random.inl
fuzzer.cc
hasher.h hasher.cc hasher.inl
siphash.h siphash.c)
target_link_libraries(fuzzer Legion::Legion)
set_target_properties(fuzzer PROPERTIES CXX_STANDARD 17)
Expand Down
55 changes: 45 additions & 10 deletions src/deterministic_random.cc
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,31 @@

#include "siphash.h"

RngSeed::RngSeed() : seed(UINT64_MAX), stream(0) {}

RngSeed::RngSeed(uint64_t _seed) : seed(_seed), stream(0) {}

RngStream RngSeed::make_stream() {
if (seed == UINT64_MAX) {
abort(); // use of invalid RngSeed
}
RngStream result(seed, stream++);
return result;
}

RngSeed::RngSeed(RngSeed &&rng) : seed(rng.seed), stream(rng.stream) {
rng.seed = UINT64_MAX;
rng.stream = 0;
}

RngSeed &RngSeed::operator=(RngSeed &&rng) {
seed = rng.seed;
stream = rng.stream;
rng.seed = UINT64_MAX;
rng.stream = 0;
return *this;
}

RngStream::RngStream(uint64_t _seed, uint64_t _stream)
: seed(_seed), stream(_stream), seq(0) {}

Expand All @@ -39,15 +57,8 @@ static void gen_bits(const uint8_t *input, size_t input_bytes, uint8_t *output,
siphash(input, input_bytes, k, output, output_bytes);
}

uint64_t RngStream::uniform_uint64_t() {
const uint64_t input[3] = {seed, stream, seq++};
uint64_t result;
gen_bits(reinterpret_cast<const uint8_t *>(&input), sizeof(input),
reinterpret_cast<uint8_t *>(&result), sizeof(result));
return result;
}

uint64_t RngStream::uniform_range(uint64_t range_lo, uint64_t range_hi /* inclusive */) {
template <typename T>
uint64_t uniform_range(T &rng, uint64_t range_lo, uint64_t range_hi /* inclusive */) {
if (range_hi <= range_lo) {
return range_lo;
}
Expand All @@ -60,7 +71,31 @@ uint64_t RngStream::uniform_range(uint64_t range_lo, uint64_t range_hi /* inclus
// loop (for small ranges), so the expected trip count is 1.
uint64_t bits;
do {
bits = uniform_uint64_t();
bits = rng.uniform_uint64_t();
} while (bits >= UINT64_MAX - remainder);
return range_lo + (bits % range_size);
}

uint64_t RngStream::uniform_uint64_t() {
const uint64_t input[3] = {seed, stream, seq++};
uint64_t result;
gen_bits(reinterpret_cast<const uint8_t *>(&input), sizeof(input),
reinterpret_cast<uint8_t *>(&result), sizeof(result));
return result;
}

uint64_t RngStream::uniform_range(uint64_t range_lo, uint64_t range_hi /* inclusive */) {
return ::uniform_range(*this, range_lo, range_hi);
}

uint64_t RngChannel::uniform_uint64_t() {
const uint64_t input[4] = {seed, stream, channel, seq++};
uint64_t result;
gen_bits(reinterpret_cast<const uint8_t *>(&input), sizeof(input),
reinterpret_cast<uint8_t *>(&result), sizeof(result));
return result;
}

uint64_t RngChannel::uniform_range(uint64_t range_lo, uint64_t range_hi /* inclusive */) {
return ::uniform_range(*this, range_lo, range_hi);
}
45 changes: 39 additions & 6 deletions src/deterministic_random.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,27 @@
#include <cstdint>
#include <type_traits>

class RngSeed;
#include "hasher.h"

class RngStream;
class RngChannel;

class RngSeed {
public:
RngSeed();
RngSeed(uint64_t seed);

RngSeed(const RngSeed &rng) = delete;
RngSeed(RngSeed &&rng);
RngSeed &operator=(const RngSeed &rng) = delete;
RngSeed &operator=(RngSeed &&rng);

RngStream make_stream();

private:
uint64_t seed;
uint64_t stream;
};

class RngStream {
private:
Expand All @@ -44,6 +64,9 @@ class RngStream {
uint64_t uniform_uint64_t();
uint64_t uniform_range(uint64_t range_lo, uint64_t range_hi /* inclusive */);

template <typename T>
RngChannel make_channel(const T &hashable) const;

private:
const uint64_t seed;
const uint64_t stream;
Expand All @@ -53,15 +76,25 @@ class RngStream {
};
static_assert(std::is_trivially_copyable_v<RngStream>);

class RngSeed {
class RngChannel {
private:
template <typename T>
RngChannel(uint64_t seed, uint64_t stream, const T &hashable);

public:
RngSeed(uint64_t seed);
RngStream make_stream();
uint64_t uniform_uint64_t();
uint64_t uniform_range(uint64_t range_lo, uint64_t range_hi /* inclusive */);

private:
const uint64_t seed;
uint64_t stream;
const uint64_t stream;
const uint64_t channel;
uint64_t seq;

friend class RngStream;
};
static_assert(std::is_trivially_copyable_v<RngSeed>);
static_assert(std::is_trivially_copyable_v<RngChannel>);

#include "deterministic_random.inl"

#endif // DETERMINISTIC_RANDOM_H_
23 changes: 23 additions & 0 deletions src/deterministic_random.inl
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/* 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.
*/

template <typename T>
RngChannel RngStream::make_channel(const T &hashable) const {
return RngChannel(seed, stream, hashable);
}

template <typename T>
RngChannel::RngChannel(uint64_t _seed, uint64_t _stream, const T &hashable)
: seed(_seed), stream(_stream), channel(hash(hashable)), seq(0) {}
39 changes: 35 additions & 4 deletions src/fuzzer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -39,14 +39,15 @@ enum TaskIDs {
enum ProjectionIDs {
PROJECTION_OFFSET_1_ID = 1,
PROJECTION_OFFSET_2_ID = 2,
PROJECTION_LAST_DISJOINT_ID = PROJECTION_OFFSET_2_ID,
PROJECTION_RANDOM_DEPTH_1_ID = 3,
PROJECTION_RANDOM_DEPTH_0_ID = 3,
};

#define LOG_ONCE(x) runtime->log_once(ctx, (x))

static Logger log_fuzz("fuzz");

static RngSeed root_seed;

static long long parse_long_long(const std::string &flag, const std::string &arg) {
long long result;
size_t consumed;
Expand Down Expand Up @@ -148,6 +149,26 @@ class OffsetProjection : public ProjectionFunctor {
uint64_t offset;
};

class RandomProjection : public ProjectionFunctor {
public:
RandomProjection(RngStream _stream) : stream(_stream) {}
bool is_functional(void) const override { return true; }
bool is_invertible(void) const override { return false; }
unsigned get_depth(void) const override { return 0; }
LogicalRegion project(LogicalPartition upper_bound, const DomainPoint &point,
const Domain &launch_domain) override {
RngChannel rng = stream.make_channel(std::pair(point, launch_domain));
Domain color_space =
runtime->get_index_partition_color_space(upper_bound.get_index_partition());
Rect<1> rect = color_space;
uint64_t index = rng.uniform_range(rect.lo[0], rect.hi[0]);
return runtime->get_logical_subregion_by_color(upper_bound, index);
}

protected:
RngStream stream;
};

template <typename T>
const T unpack_args(const Task *task) {
if (task->arglen != sizeof(T)) {
Expand Down Expand Up @@ -740,7 +761,8 @@ class RequirementBuilder {
void select_projection(RngStream &rng, bool requires_projection) {
projection = LEGION_MAX_APPLICATION_PROJECTION_ID;
if (requires_projection) {
switch (rng.uniform_range(0, 2)) {
uint64_t max_id = need_disjoint() ? 2 : 3;
switch (rng.uniform_range(0, max_id)) {
case 0: {
projection = 0; // identity projection functor
} break;
Expand All @@ -750,6 +772,9 @@ class RequirementBuilder {
case 2: {
projection = PROJECTION_OFFSET_2_ID;
} break;
case 3: {
projection = PROJECTION_RANDOM_DEPTH_0_ID;
} break;
default:
abort();
}
Expand Down Expand Up @@ -1116,7 +1141,7 @@ void top_level(const Task *task, const std::vector<PhysicalRegion> &regions, Con
FuzzerConfig config = FuzzerConfig::parse_args(args.argc, args.argv);
config.log_config(runtime, ctx);

RngSeed seed(config.initial_seed);
RngSeed seed = std::move(root_seed);
RngStream rng = seed.make_stream();

RegionForest forest(runtime, ctx, config, seed);
Expand Down Expand Up @@ -1149,10 +1174,16 @@ void top_level(const Task *task, const std::vector<PhysicalRegion> &regions, Con
}

int main(int argc, char **argv) {
Runtime::initialize(&argc, &argv, true /* filter */);
FuzzerConfig config = FuzzerConfig::parse_args(argc, argv);
root_seed = RngSeed(config.initial_seed);

Runtime::preregister_projection_functor(PROJECTION_OFFSET_1_ID,
new OffsetProjection(1));
Runtime::preregister_projection_functor(PROJECTION_OFFSET_2_ID,
new OffsetProjection(2));
Runtime::preregister_projection_functor(PROJECTION_RANDOM_DEPTH_0_ID,
new RandomProjection(root_seed.make_stream()));

Runtime::set_top_level_task_id(TOP_LEVEL_TASK_ID);
{
Expand Down
42 changes: 42 additions & 0 deletions src/hasher.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/* 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 "hasher.h"

#include <sstream>

#include "siphash.h"

static void hash_bytes(const uint8_t *input, size_t input_bytes, uint8_t *output,
size_t output_bytes) {
// Choose different magic numbers to avoid colliding with gen_bits.
const uint8_t k[16] = {16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31};
siphash(input, input_bytes, k, output, output_bytes);
}

Hasher::Hasher() {}

void Hasher::hash_type_tag(HashTypeTag type_tag) {
buffer.write(reinterpret_cast<const char *>(&type_tag), sizeof(type_tag));
}

uint64_t Hasher::result() {
uint64_t result;
std::string content = std::move(buffer).str();
static_assert(sizeof(char) == sizeof(uint8_t));
hash_bytes(reinterpret_cast<const uint8_t *>(content.data()), content.size(),
reinterpret_cast<uint8_t *>(&result), sizeof(result));
return result;
}
29 changes: 29 additions & 0 deletions src/hasher.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/* 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 HASHER_H_
#define HASHER_H_

#include <cstdint>
#include <sstream>

#include "legion.h"

template <typename T>
uint64_t hash(const T &value);

#include "hasher.inl"

#endif // HASHER_H_
Loading

0 comments on commit 8f6b307

Please sign in to comment.