This is an archive of the discontinued LLVM Phabricator instance.

[libc] Support 'assert.h' on the GPU
ClosedPublic

Authored by jhuber6 on Aug 31 2023, 10:19 AM.

Details

Summary

This patch adds the necessary support to provide assert functionality
through the GPU libc implementation. This implementation creates a
special-case GPU implementation rather than relying on the common
version. This is because the GPU has special considerings for printing.
The assertion is printed out in chunks with write_to_stderr, however
when combined with the GPU execution model this causes 32+ threads to
all execute in-lock step. Meaning that we'll get a horribly fragmented
message. Furthermore, potentially thousands of threads could hit the
assertion at once and try to print even if we had it all in one
printf.

This is solved by having a one-time lock that each thread group / wave /
warp will attempt to claim. We only let one thread group pass through
while the others simply stop executing. Finally only the first thread in
that group will do the printing until we finally abort execution.

Diff Detail

Event Timeline

jhuber6 created this revision.Aug 31 2023, 10:19 AM
Herald added projects: Restricted Project, Restricted Project. · View Herald TranscriptAug 31 2023, 10:19 AM
jhuber6 requested review of this revision.Aug 31 2023, 10:19 AM

I don't think the multiple writes to stderr in the normal implementation is an inherently good feature, how about we change the assert implementation on all platforms to compose a single write to stderr?

sivachandra added inline comments.Aug 31 2023, 10:33 AM
libc/src/assert/CMakeLists.txt
2

For the sake of consistency with other directories, you should move the generic implementation to a generic directory and list only an alias here:

if(TARGET libc.src.asser.${LIBC_TARGET_OS}.__assert_fail)
  set(assert_fail_dep libc.src.asser.${LIBC_TARGET_OS}.__assert_fail)
else()
  set(assert_fail_dep libc.src.assert.generic.__assert_fail)
endif()

add_entrypoint_object(
  __assert_fail
      ALIAS
      DEPENDS
        $[assert_fail_dep}
)
jhuber6 updated this revision to Diff 555105.Aug 31 2023, 11:00 AM

Address comments.

I don't think the multiple writes to stderr in the normal implementation is an inherently good feature, how about we change the assert implementation on all platforms to compose a single write to stderr?

It'd probably still be sufficiently different because of the warp level operations. I'll leave it to @sivachandra if he wants single printer semantics for this.

Did you move the generic __assert_fail.cpp file?

I don't think the multiple writes to stderr in the normal implementation is an inherently good feature, how about we change the assert implementation on all platforms to compose a single write to stderr?

It'd probably still be sufficiently different because of the warp level operations. I'll leave it to @sivachandra if he wants single printer semantics for this.

I will change it separate from this patch.

jhuber6 updated this revision to Diff 555107.Aug 31 2023, 11:18 AM

I knew I was forgetting something.

jhuber6 updated this revision to Diff 555108.Aug 31 2023, 11:19 AM

And headers

jhuber6 updated this revision to Diff 555125.Aug 31 2023, 11:47 AM

More explicitly require that only the first lane does the atomic loading so that broadcast_value works.

sivachandra accepted this revision.Aug 31 2023, 12:06 PM

OK for structuring changes.

This revision is now accepted and ready to land.Aug 31 2023, 12:06 PM

Instead of this bespoke locking stuff, how about

if (gpu::is_first_lane(mask)) {
  report_assertion_failure();
  abort();
} else {
  endpgm();
}

?

Instead of this bespoke locking stuff, how about

if (gpu::is_first_lane(mask)) {
  report_assertion_failure();
  abort();
} else {
  endpgm();
}

?

endpgm on AMDGPU kills the whole wavefront. So you'd need to make sure that the printing and everything is done strictly first.

This revision was landed with ongoing or failed builds.Aug 31 2023, 1:04 PM
This revision was automatically updated to reflect the committed changes.