Skip to content

Conversation

TH3CHARLie
Copy link
Contributor

This PR attempts to merge the random pipeline generator that is used to generate autoscheduling training data into main, originally from: https://github.com/halide/Halide/tree/abadams/random_pipelines/

One thing I'm not sure about is do we want to include

  1. A similar driver code process.cpp like other apps that just test if the generator code can compile and run (see examples like bgu)
  2. the autotune script that actually uses the generator to generate the schedule (see Andrew's original branch)

cc @abadams @alexreinking

@abadams
Copy link
Member

abadams commented Oct 3, 2025

I think we need to have some way to compile and run it, and some build target that does so. Maybe RunGen-based?

Copy link
Member

@alexreinking alexreinking left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have some feedback re: the handling of randomness in this. There are good utilities in C++ for generating uniform randomness. Using mod introduces bias. I'm not sure about the division thing for floats either.

result.push_back(i);
}
return result;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This could at least take a const reference, but it could be more simply written as

vector<Expr> arguments{vars.begin(), vars.end()};

wherever it is used.

}
float rand_float() {
return rand_int(0, 1 << 30) / (float)(1 << 30);
}
Copy link
Member

@alexreinking alexreinking Oct 4, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is janky. We should really use the proper RNG types...

class Random {
    std::mt19937 eng_;
    uint32_t seed_;

   public:
    explicit Random(uint32_t seed) : eng_(seed), seed_(seed) {}

    void reseed(uint32_t seed) {
        eng_.seed(seed);
        seed_ = seed;
    }

    uint32_t seed() const { return seed_; }

    int integer(int min, int max) {
        std::uniform_int_distribution<int> dist(min, max);
        return dist(eng_);
    }

    bool boolean(double p = 0.5) {
        std::bernoulli_distribution dist(p);
        return dist(eng_);
    }

    float real() {
        std::uniform_real_distribution<float> dist(0.0f, 1.0f);
        return dist(eng_);
    }

    template <typename T>
    decltype(auto) element(T&& t) {
        auto n = std::size(t);
        std::uniform_int_distribution<std::size_t> dist(0, n - 1);
        return t[dist(eng_)];
    }
};

Random R;

Something like this should work.

// subexpressions. At the base case where depth is 0, we just return
// a randomly chosen input.
Type expr_types[] = {UInt(8), UInt(16), UInt(32), Int(8), Int(16), Int(32), Float(32)};
const int expr_type_count = sizeof(expr_types) / sizeof(expr_types[0]);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need for the _count if we use the element helper above.

Comment on lines +89 to +90
int op = rng() % comp_bin_op_count;
return make_comp_bin_op[op](a, b);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
int op = rng() % comp_bin_op_count;
return make_comp_bin_op[op](a, b);
return R.element(make_comp_bin_op)(a, b);

Comment on lines +75 to +77
const int bin_op_count = sizeof(make_bin_op) / sizeof(make_bin_op[0]);
const int bool_bin_op_count = sizeof(make_bool_bin_op) / sizeof(make_bool_bin_op[0]);
const int comp_bin_op_count = sizeof(make_comp_bin_op) / sizeof(make_comp_bin_op[0]);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need for counts

} else if (t.is_int() || t.is_uint()) {
return cast(t, rand_int(1, 127));
} else if (t.is_float()) {
return cast(t, rand_float());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
return cast(t, rand_float());
return cast(t, R.real());

}

void generate() {
rng.seed((int)seed);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
rng.seed((int)seed);
R.reseed(seed);

public:
int num_stage_types = 18;
// The random seed to use to generate the pipeline.
GeneratorParam<int> seed{"seed", 1};
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
GeneratorParam<int> seed{"seed", 1};
GeneratorParam<uint32_t> seed{"seed", 1};

}
};

HALIDE_REGISTER_GENERATOR(RandomPipeline, random_pipeline) No newline at end of file
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Newline

add_app(unsharp)
add_app(wavelet)
add_app(HelloBaremetal)
add_app(random_pipeline)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please insert this in alphabetical order (and fix HelloBaremetal, apparently)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants