Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Anderson2021 autoscheduler triggers "producer_store_instances > 0" #93

Open
antonysigma opened this issue Oct 24, 2023 · 5 comments
Open
Assignees

Comments

@antonysigma
Copy link
Collaborator

Working draft for debugging purpose: https://github.com/antonysigma/proximal/tree/debug-producer-error

Observations: when we define the Halide Func and then return them as std::tuple, the generator can capture the algorithm pipeline and schedule it with Mullapudi2016 autoscheduler. But not Anderson2021. The autoscheduler reports:

Unhandled exception: Internal Error at .../autoschedulers/anderson2021/LoopNest.cpp:2747
triggered by user code at :
Condition failed: producer_store_instances > 0:

The same assertion failure happens with C++ structured bindings, as well as passing return values as function reference.

The offending line is shown below:

using Halide::Func
template<size_t N> using FuncTuple = std::array<Func, N>;
std::vector<Func> v_list(n_iter);
std::vector<FuncTuple<psi_size>> z_list(n_iter);
std::vector<FuncTuple<psi_size>> u_list(n_iter);

for (size_t i = 0; i < n_iter; i++) {
    std::tie(v_list[i], z_list[i], u_list[i]) = algorithm::linearized_admm::iterate(
        v, z_prev, u_prev, K, omega_fn, psi_fns, lmb, mu, input);
}

See also: #67 .

@antonysigma antonysigma self-assigned this Oct 24, 2023
@antonysigma
Copy link
Collaborator Author

antonysigma commented Oct 24, 2023

Note to self: the Anderson2021-specific assertion failure producer_store_instances > 0 is eliminated when the returned Func, captured via structured binding, is in-turn copied to the target Func via the elementwise operation. Copy assignment operator doesn't work.

In other words, the following code triggers assertion failure:

std::tie(v_list[i], z_list[i], u_list[i])
    = algorithm::linearized_admm::iterate(
    v, z_prev, u_prev, K, omega_fn, psi_fns, lmb, mu, input);

This too:

const auto [_v_new, z_new, u_new]
    = algorithm::linearized_admm::iterate(
    v, z_prev, u_prev, K, omega_fn, psi_fns, lmb, mu, input);

v_list[i] = _v_new;
z_list[i] = z_new;
u_list[i] = u_new;

And this works:

const auto [_v_new, z_new, u_new]
    = algorithm::linearized_admm::iterate(
    v, z_prev, u_prev, K, omega_fn, psi_fns, lmb, mu, input);

using Halide::_;
v_list[i](x, y, c, _) = _v_new(x, y, c, _);

std::copy(u_new.begin(), u_new.end(), u_list[i].begin());

std::transform(z_new.begin(), z_new.end(), z_list[i].begin(), [](const auto& _z) -> Func{
    Func _z_new;
    _z_new(x, y, c, _) = _z(x, y, c, _);
    return _z_new;
});

@antonysigma antonysigma changed the title Anderson2021 autoscheduler triggers "producer_tore_instances > 0" Anderson2021 autoscheduler triggers "producer_store_instances > 0" Oct 25, 2023
@antonysigma
Copy link
Collaborator Author

Hi @aekul,

Just curious, what does Condition failed: producer_store_instances > 0 do in the autoscheduler? I am using C++17's structured binding syntax to capture Functions as std::tuple, but the Anderson2021 auto-scheduler doesn't seem to like it.

https://github.com/halide/Halide/blob/186510173d4a9f344ef365e2ccc334e90aacec41/src/autoschedulers/anderson2021/LoopNest.cpp#L2742-L2747

Comparing the code between Anderson2021 and Adams2019, the key difference is in the condition producer_has_been_scheduled. What does it do? And, how do I get started to debug my code?

@aekul
Copy link

aekul commented Nov 11, 2023

producer_store_instances should be the number of times the producer is allocated e.g. if the producer is stored at root, then it will be allocated once so producer_store_instances will be 1. I would expect it to always be >= 1 (assuming that the value has actually been computed already) since there must be at least 1 allocation, so I think that's what the assert is checking.

I haven't had a chance to look too closely and don't recall all the details but producer_has_been_scheduled is true for inputs and when site.produce != nullptr (we know the loop nest where it will be produced). It sounds like the producer's featurization has not been computed for some reason.

For debugging, it would be useful to know whether producer_has_been_scheduled is true and which stage the producer is. You could then try to see if that stage does in fact have its featurization computed or not. If you can reduce this to a more minimal example, I can potentially take a closer look too.

@antonysigma
Copy link
Collaborator Author

Thanks @aekul for the guidance. I will start by printing the current stage and the input stage names -- just to identify the halide Stage causing the assertion failure. It should help me further reduce the repo code size for further debugging purposes.

@antonysigma
Copy link
Collaborator Author

antonysigma commented Nov 14, 2023

Note to self: producer_has_been_scheduled is false at the following expression. Consumer = u_new$1, producer = _z. site.produce is nullptr. I will continue to debug...

FuncTuple<N> u_new;
ranges::transform(zip_view{u, Kv2, z_new, psi_fns}, u_new.begin(), [=](const auto& args) -> Func {
const auto& [_u, _Kv, _z, prox] = args;
const auto vars = (prox.n_dim == 4) ? Vars{x, y, c, k} : Vars{x, y, c};
Func _u_new{"u_new"};
_u_new(vars) = _u(vars) + _Kv(vars) - _z(vars);
return _u_new;
});

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

No branches or pull requests

2 participants