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

[Debug only; Do not merge] Debug the ASAN error w/ Anderson2021 #7699

Closed

Conversation

antonysigma
Copy link
Contributor

Provide a minimal reproducible test case where the Anderson2021 autoscheduler failed with segmentation fault. Primarily the L2 norm user defined function.

Contact me if you wish to rebase the changes on top of Halide v16.0.0.

Expected ASAN error:

env LD_LIBRARY_PATH=/home/antony/Projects/ProxImaL/proximal/halide/subprojects/Halide-16.0.0-x86-64-linux/lib /home/antony/Projects/ProxImaL/proximal/halide/build-clang/src/user-problem/solver-generator -o /home/antony/Projects/ProxImaL/proximal/halide/build-clang/src/user-problem -g debug_norm -e static_library,h target=host-cuda-cuda_capability_75 -p autoschedule_anderson2021 autoscheduler=Anderson2021 autoscheduler.parallelism=32
AddressSanitizer:DEADLYSIGNAL
=================================================================
==1236944==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000070 (pc 0x7f00983507ce bp 0x000000000008 sp 0x7ffe56413000 T0)
==1236944==The signal is caused by a READ memory access.
==1236944==Hint: address points to the zero page.
    #0 0x7f00983507ce in Halide::Internal::Autoscheduler::LoopNest::compute_strides(Halide::Internal::Autoscheduler::LoadJacobian const&, int, Halide::Internal::Autoscheduler::FunctionDAG::Node const*, Halide::Internal::IntrusivePtr<Halide::Internal::Autoscheduler::BoundContents const> const&, Halide::Internal::Autoscheduler::ThreadInfo const&, bool) const (/home/antony/Projects/ProxImaL/proximal/halide/subprojects/Halide-16.0.0-x86-64-linux/lib/libautoschedule_anderson2021.so+0x657ce)
    #1 0x7f0098372f6c in void Halide::Internal::Autoscheduler::LoopNest::compute_num_mem_accesses_per_block<Halide::Internal::Autoscheduler::GlobalMem>(Halide::Internal::Autoscheduler::LoadJacobian const&, Halide::Internal::Autoscheduler::FunctionDAG::Node const*, Halide::Internal::IntrusivePtr<Halide::Internal::Autoscheduler::BoundContents const> const&, Halide::Internal::Autoscheduler::ThreadInfo const&, int, double, Halide::Internal::Autoscheduler::MemInfo<Halide::Internal::Autoscheduler::MemTraits<Halide::Internal::Autoscheduler::GlobalMem>::MemInfoType>&, bool) const (/home/antony/Projects/ProxImaL/proximal/halide/subprojects/Halide-16.0.0-x86-64-linux/lib/libautoschedule_anderson2021.so+0x87f6c)
    #2 0x7f0098373f9d in void Halide::Internal::Autoscheduler::LoopNest::compute_mem_load_features<Halide::Internal::Autoscheduler::GlobalMem>(Halide::Internal::Autoscheduler::LoadJacobian const&, int, Halide::Internal::Autoscheduler::FunctionDAG::Node const*, Halide::Internal::IntrusivePtr<Halide::Internal::Autoscheduler::BoundContents const> const&, bool, Halide::Internal::Autoscheduler::ThreadInfo const&, Halide::Internal::Autoscheduler::MemInfo<Halide::Internal::Autoscheduler::MemTraits<Halide::Internal::Autoscheduler::GlobalMem>::MemInfoType>&, double, bool) const (/home/antony/Projects/ProxImaL/proximal/halide/subprojects/Halide-16.0.0-x86-64-linux/lib/libautoschedule_anderson2021.so+0x88f9d)
    #3 0x7f009835ca37 in Halide::Internal::Autoscheduler::LoopNest::compute_features(Halide::Internal::Autoscheduler::FunctionDAG const&, Halide::Internal::Autoscheduler::Anderson2021Params const&, Halide::Target const&, PerfectHashMap<Halide::Internal::Autoscheduler::FunctionDAG::Node::Stage, Halide::Internal::Autoscheduler::LoopNest::Sites, 4, PerfectHashMapAsserter> const&, long, long, Halide::Internal::Autoscheduler::LoopNest const*, Halide::Internal::Autoscheduler::LoopNest const*, Halide::Internal::Autoscheduler::LoopNest const&, Halide::Internal::Autoscheduler::GPULoopInfo, bool, PerfectHashMap<Halide::Internal::Autoscheduler::FunctionDAG::Node::Stage, long, 4, PerfectHashMapAsserter> const&, long*, long*, long*, PerfectHashMap<Halide::Internal::Autoscheduler::FunctionDAG::Node::Stage, Halide::Internal::ScheduleFeatures, 4, PerfectHashMapAsserter>*, Halide::Internal::Autoscheduler::Statistics&, bool) const (/home/antony/Projects/ProxImaL/proximal/halide/subprojects/Halide-16.0.0-x86-64-linux/lib/libautoschedule_anderson2021.so+0x71a37)
    #4 0x7f009835b0ab in Halide::Internal::Autoscheduler::LoopNest::compute_features(Halide::Internal::Autoscheduler::FunctionDAG const&, Halide::Internal::Autoscheduler::Anderson2021Params const&, Halide::Target const&, PerfectHashMap<Halide::Internal::Autoscheduler::FunctionDAG::Node::Stage, Halide::Internal::Autoscheduler::LoopNest::Sites, 4, PerfectHashMapAsserter> const&, long, long, Halide::Internal::Autoscheduler::LoopNest const*, Halide::Internal::Autoscheduler::LoopNest const*, Halide::Internal::Autoscheduler::LoopNest const&, Halide::Internal::Autoscheduler::GPULoopInfo, bool, PerfectHashMap<Halide::Internal::Autoscheduler::FunctionDAG::Node::Stage, long, 4, PerfectHashMapAsserter> const&, long*, long*, long*, PerfectHashMap<Halide::Internal::Autoscheduler::FunctionDAG::Node::Stage, Halide::Internal::ScheduleFeatures, 4, PerfectHashMapAsserter>*, Halide::Internal::Autoscheduler::Statistics&, bool) const (/home/antony/Projects/ProxImaL/proximal/halide/subprojects/Halide-16.0.0-x86-64-linux/lib/libautoschedule_anderson2021.so+0x700ab)
    #5 0x7f009835ac49 in Halide::Internal::Autoscheduler::LoopNest::compute_features(Halide::Internal::Autoscheduler::FunctionDAG const&, Halide::Internal::Autoscheduler::Anderson2021Params const&, Halide::Target const&, PerfectHashMap<Halide::Internal::Autoscheduler::FunctionDAG::Node::Stage, Halide::Internal::Autoscheduler::LoopNest::Sites, 4, PerfectHashMapAsserter> const&, long, long, Halide::Internal::Autoscheduler::LoopNest const*, Halide::Internal::Autoscheduler::LoopNest const*, Halide::Internal::Autoscheduler::LoopNest const&, Halide::Internal::Autoscheduler::GPULoopInfo, bool, PerfectHashMap<Halide::Internal::Autoscheduler::FunctionDAG::Node::Stage, long, 4, PerfectHashMapAsserter> const&, long*, long*, long*, PerfectHashMap<Halide::Internal::Autoscheduler::FunctionDAG::Node::Stage, Halide::Internal::ScheduleFeatures, 4, PerfectHashMapAsserter>*, Halide::Internal::Autoscheduler::Statistics&, bool) const (/home/antony/Projects/ProxImaL/proximal/halide/subprojects/Halide-16.0.0-x86-64-linux/lib/libautoschedule_anderson2021.so+0x6fc49)
    #6 0x7f009838c1bd in Halide::Internal::Autoscheduler::State::compute_featurization(Halide::Internal::Autoscheduler::FunctionDAG const&, Halide::Internal::Autoscheduler::Anderson2021Params const&, Halide::Target const&, PerfectHashMap<Halide::Internal::Autoscheduler::FunctionDAG::Node::Stage, Halide::Internal::ScheduleFeatures, 4, PerfectHashMapAsserter>*, Halide::Internal::Autoscheduler::Statistics&, bool) const (/home/antony/Projects/ProxImaL/proximal/halide/subprojects/Halide-16.0.0-x86-64-linux/lib/libautoschedule_anderson2021.so+0xa11bd)
    #7 0x7f009838cec0 in Halide::Internal::Autoscheduler::State::calculate_cost(Halide::Internal::Autoscheduler::FunctionDAG const&, Halide::Internal::Autoscheduler::Anderson2021Params const&, Halide::Target const&, Halide::CostModel*, Halide::Internal::Autoscheduler::Statistics&, bool) (/home/antony/Projects/ProxImaL/proximal/halide/subprojects/Halide-16.0.0-x86-64-linux/lib/libautoschedule_anderson2021.so+0xa1ec0)
    #8 0x7f009837c076 in Halide::Internal::Autoscheduler::SearchSpace::add_child(Halide::Internal::IntrusivePtr<Halide::Internal::Autoscheduler::State> const&, Halide::Internal::IntrusivePtr<Halide::Internal::Autoscheduler::LoopNest const> const&, std::function<void (Halide::Internal::IntrusivePtr<Halide::Internal::Autoscheduler::State>&&)>&) const (/home/antony/Projects/ProxImaL/proximal/halide/subprojects/Halide-16.0.0-x86-64-linux/lib/libautoschedule_anderson2021.so+0x91076)
    #9 0x7f0098381839 in Halide::Internal::Autoscheduler::SearchSpace::generate_children(Halide::Internal::IntrusivePtr<Halide::Internal::Autoscheduler::State> const&, std::function<void (Halide::Internal::IntrusivePtr<Halide::Internal::Autoscheduler::State>&&)>&, int, bool) (/home/antony/Projects/ProxImaL/proximal/halide/subprojects/Halide-16.0.0-x86-64-linux/lib/libautoschedule_anderson2021.so+0x96839)
    #10 0x7f009830926e in Halide::Internal::Autoscheduler::AutoSchedule::optimal_schedule_pass(int, int, int, Halide::Internal::Autoscheduler::ProgressBar&, std::unordered_set<unsigned long, std::hash<unsigned long>, std::equal_to<unsigned long>, std::allocator<unsigned long> >&) (/home/antony/Projects/ProxImaL/proximal/halide/subprojects/Halide-16.0.0-x86-64-linux/lib/libautoschedule_anderson2021.so+0x1e26e)
    #11 0x7f009830b144 in Halide::Internal::Autoscheduler::AutoSchedule::optimal_schedule(int) (/home/antony/Projects/ProxImaL/proximal/halide/subprojects/Halide-16.0.0-x86-64-linux/lib/libautoschedule_anderson2021.so+0x20144)
    #12 0x7f009830c0d2 in Halide::Internal::Autoscheduler::generate_schedule(std::vector<Halide::Internal::Function, std::allocator<Halide::Internal::Function> > const&, Halide::Target const&, Halide::Internal::Autoscheduler::Anderson2021Params const&, Halide::AutoSchedulerResults*) (/home/antony/Projects/ProxImaL/proximal/halide/subprojects/Halide-16.0.0-x86-64-linux/lib/libautoschedule_anderson2021.so+0x210d2)
    #13 0x7f0098317f4b in Halide::Internal::Autoscheduler::Anderson2021::operator()(Halide::Pipeline const&, Halide::Target const&, Halide::AutoschedulerParams const&, Halide::AutoSchedulerResults*) (/home/antony/Projects/ProxImaL/proximal/halide/subprojects/Halide-16.0.0-x86-64-linux/lib/libautoschedule_anderson2021.so+0x2cf4b)
    #14 0x7f009cf22c82 in Halide::Pipeline::apply_autoscheduler(Halide::Target const&, Halide::AutoschedulerParams const&) const (/home/antony/Projects/ProxImaL/proximal/halide/subprojects/Halide-16.0.0-x86-64-linux/lib/libHalide.so.16+0xd9fc82)
    #15 0x7f009ca56e7c in Halide::Internal::AbstractGenerator::build_module(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) (/home/antony/Projects/ProxImaL/proximal/halide/subprojects/Halide-16.0.0-x86-64-linux/lib/libHalide.so.16+0x8d3e7c)
    #16 0x7f009cd78eaa in std::_Function_handler<Halide::Module (std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, Halide::Target const&), Halide::Internal::execute_generator(Halide::Internal::ExecuteGeneratorArgs const&)::'lambda2'(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, Halide::Target const&)>::_M_invoke(std::_Any_data const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, Halide::Target const&) (/home/antony/Projects/ProxImaL/proximal/halide/subprojects/Halide-16.0.0-x86-64-linux/lib/libHalide.so.16+0xbf5eaa)
    #17 0x7f009ceec309 in Halide::compile_multitarget(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::map<Halide::OutputFileType, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::less<Halide::OutputFileType>, std::allocator<std::pair<Halide::OutputFileType const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > > const&, std::vector<Halide::Target, std::allocator<Halide::Target> > const&, std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const&, std::function<Halide::Module (std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, Halide::Target const&)> const&, std::function<std::unique_ptr<Halide::Internal::CompilerLogger, std::default_delete<Halide::Internal::CompilerLogger> > (std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, Halide::Target const&)> const&) (/home/antony/Projects/ProxImaL/proximal/halide/subprojects/Halide-16.0.0-x86-64-linux/lib/libHalide.so.16+0xd69309)
    #18 0x7f009cd81edf in Halide::Internal::execute_generator(Halide::Internal::ExecuteGeneratorArgs const&) (/home/antony/Projects/ProxImaL/proximal/halide/subprojects/Halide-16.0.0-x86-64-linux/lib/libHalide.so.16+0xbfeedf)
    #19 0x7f009cd834ed in Halide::Internal::(anonymous namespace)::generate_filter_main_inner(int, char**, Halide::Internal::GeneratorFactoryProvider const&) (/home/antony/Projects/ProxImaL/proximal/halide/subprojects/Halide-16.0.0-x86-64-linux/lib/libHalide.so.16+0xc004ed)
    #20 0x7f009cd8427f in Halide::Internal::generate_filter_main(int, char**, Halide::Internal::GeneratorFactoryProvider const&) (/home/antony/Projects/ProxImaL/proximal/halide/subprojects/Halide-16.0.0-x86-64-linux/lib/libHalide.so.16+0xc0127f)
    #21 0x7f009cd842ca in Halide::Internal::generate_filter_main(int, char**) (/home/antony/Projects/ProxImaL/proximal/halide/subprojects/Halide-16.0.0-x86-64-linux/lib/libHalide.so.16+0xc012ca)
    #22 0x7f009bc0c082 in __libc_start_main /build/glibc-SzIz7B/glibc-2.31/csu/../csu/libc-start.c:308:16
    #23 0x42346d in _start (/home/antony/Projects/ProxImaL/proximal/halide/build-clang/src/user-problem/solver-generator+0x42346d)

AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV (/home/antony/Projects/ProxImaL/proximal/halide/subprojects/Halide-16.0.0-x86-64-linux/lib/libautoschedule_anderson2021.so+0x657ce) in Halide::Internal::Autoscheduler::LoopNest::compute_strides(Halide::Internal::Autoscheduler::LoadJacobian const&, int, Halide::Internal::Autoscheduler::FunctionDAG::Node const*, Halide::Internal::IntrusivePtr<Halide::Internal::Autoscheduler::BoundContents const> const&, Halide::Internal::Autoscheduler::ThreadInfo const&, bool) const
==1236944==ABORTING

Provide a minimal reproducable test case where the Anderson2021 failed
with segmentation fault. Primarily the L2 norm user defined function.
@antonysigma antonysigma force-pushed the debug-norm-anderson2021-segfault branch from 5bc3400 to 9e20f75 Compare July 24, 2023 19:06
@steven-johnson steven-johnson changed the title [Debug only; Do not merge] Debug the ASAN error w/ Anderson2019 [Debug only; Do not merge] Debug the ASAN error w/ Anderson2021 Jul 24, 2023
@steven-johnson
Copy link
Contributor

From some brief debugging, it appears that there are call site(s) that assume gpu_loop_info.thread_info can never be null, ... and yet it is, so we pass in a const ThreadInfo& that is null. Not sure how this happens.

@steven-johnson
Copy link
Contributor

To see this without asan, insert

internal_assert(gpu_loop_info.thread_info != nullptr);

at lines 846, 2332, 2364, 2405 of LoopNest.cpp

@steven-johnson
Copy link
Contributor

See #7703

@steven-johnson
Copy link
Contributor

So I think the issue here is:

  • LoopNest::compute_features() only creates a ThreadInfo if is_gpu_thread(target) is true
  • ...which is only the case if gpu_label == GPU_parallelism::Thread
  • ...which is probably never the case, since the demo_generator hack above doesn't do any gpu scheduling (!)

Then, later in LoopNest::compute_features(), calls to helper functions blithely assume that a valid ThreadInfo exists, and crashiness ensues.

I don't currently grok this code well enough to know whether we should just be creating the ThreadInfo in all cases, or doing something else later on.

@aekul
Copy link
Contributor

aekul commented Jul 29, 2023

Yes, that's right. The code assumes that every Func is surrounded by a block loop and a thread loop, which means it assumes there is always a non-null ThreadInfo object when the features are computed. But in this case, the output of the generator is a single number so the autoscheduler is currently not creating a block and thread loop for it, so the ThreadInfo object ends up being null.

2 options I'll look into:

  • Exit early since there isn't really anything being scheduled
  • Create a block and thread loop with a single iteration so that features can be computed as normal

@antonysigma
Copy link
Contributor Author

antonysigma commented Jul 31, 2023

The code assumes that every Func is surrounded by a block loop and a thread loop

Thanks @aekul for the clarification. The author of the Anderson2021 also mentioned in Section 8 the lack of rfactor optimization in the auto-scheduler algorithm.

... Making tiling decisions on a
per-stage basis is likely also necessary to support parallelizing reductions (including the Halide
scheduling options rfactor and atomic), which is an important optimization on histogram equalize.


Two options: .... Exit early since there isn't really anything being scheduled

I can anticipate an average Halide user will attempt to workaround the termination by

RDom r(0, 5);
Func s;
s(x) += input(r.x);

... followed by bounding Func s with s.bound(x, 0, 1). Not sure if it is valid though.

@aekul
Copy link
Contributor

aekul commented Aug 1, 2023

Yeah, I decided not to exit early and instead add better handling for scalars (#7726) so hopefully it should work with or without that kind of workaround

@steven-johnson
Copy link
Contributor

This should be fixed as of top-of-tree, closing (please re-open if you still find errors)

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