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

Implement printf #565

Merged
merged 13 commits into from
Jul 16, 2023
Merged

Implement printf #565

merged 13 commits into from
Jul 16, 2023

Conversation

rjodinchr
Copy link
Contributor

Clspv provides a printf definition that stores the value of each argument in a program-wide printf storage buffer. This implementation uses the appropriate ClspvReflection instructions to parse this data and print the resulting strings at runtime.

This is a rebase of #420 + some fixes

Copy link
Owner

@kpet kpet left a comment

Choose a reason for hiding this comment

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

Thanks! We can leave removing the serialisation or adding support for batching to a future PR but there are a few things we should IMO fix as part of this one. Ideally we'd add a few tests (I'm thinking of exercising the case where we wrap-around the buffer at least) but I'm fine with deferring to a separate PR if you want.

FWIW, it's passing all the printf conformance tests at my end and the validation layers do not report anything.

src/config.def Outdated Show resolved Hide resolved
src/printf.cpp Outdated Show resolved Hide resolved
src/program.cpp Outdated Show resolved Hide resolved
src/program.hpp Outdated Show resolved Hide resolved
src/queue.cpp Outdated Show resolved Hide resolved
CHECK_RETURN cl_int do_post_action() override final;

bool can_be_batched() const override final {
return !m_kernel->uses_printf() &&
Copy link
Owner

Choose a reason for hiding this comment

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

Fine as a first step but we should be able to support batching.

src/queue.hpp Outdated Show resolved Hide resolved
src/queue.cpp Outdated Show resolved Hide resolved
src/printf.cpp Outdated Show resolved Hide resolved
auto bytes_written = read_inc_buff<uint32_t>(data) * 4;
auto* data_start = data;

while (static_cast<size_t>(data - data_start) < bytes_written &&
Copy link
Owner

Choose a reason for hiding this comment

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

Does this mean that we never print anything if the kernel filled the whole buffer and we wrapped around (I haven't checked the clspv side)?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I have added a test showing that we print as much as possible.

callumfare and others added 9 commits July 10, 2023 13:58
Clspv provides a printf definition that stores the value of each argument in a
program-wide printf storage buffer. This implementation uses the appropriate
ClspvReflection instructions to parse this data and print the resulting
strings at runtime.
Co-authored-by: Kévin Petit <kpet@free.fr>
Co-authored-by: Kévin Petit <kpet@free.fr>
Co-authored-by: Kévin Petit <kpet@free.fr>
Co-authored-by: Kévin Petit <kpet@free.fr>
@rjodinchr rjodinchr requested a review from kpet July 10, 2023 12:29
@rjodinchr
Copy link
Contributor Author

As you proposed I have left removing the serialisation and adding support for batching to a future PR.

I tried to address every other comment. And I have added some tests. Especially to convert to wrapping behaviour.

Copy link
Owner

@kpet kpet left a comment

Choose a reason for hiding this comment

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

Thanks for all the changes. This is still suboptimal and broken in some cases but good enough for many common use-cases and the CTS. Let's put a stake in the ground.

Comment on lines +22 to +23
#include "spirv/unified1/NonSemanticClspvReflection.h"

Copy link
Owner

Choose a reason for hiding this comment

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

Suggested change
#include "spirv/unified1/NonSemanticClspvReflection.h"

Should no longer be necessary.

if (m_kernel->uses_printf()) {
auto buffer = m_queue->get_printf_buffer();
if (buffer == nullptr) {
cvk_error_fn("printf buffer was not created");
Copy link
Owner

Choose a reason for hiding this comment

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

I'm not sure this makes sense as a user-visible error. The only to hit this is if we made a mistake in clvk. Maybe an assert would have been enough/more appropriate.

Comment on lines +186 to +188
if (!m_printf_buffer) {
return nullptr;
}
Copy link
Owner

Choose a reason for hiding this comment

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

Don't think you need this.

Comment on lines +37 to +69
static void releaseStdout(int fd) {
fflush(stdout);
dup2(fd, fileno(stdout));
close(fd);
}

static bool getStdout(int& fd) {
fd = dup(fileno(stdout));
if (!freopen(stdoutFileName.c_str(), "w", stdout)) {
fprintf(stderr, "ERROR!\n");
releaseStdout(fd);
return false;
}
return true;
}

static char* getStdoutContent() {
FILE* f;
memset(stdoutBuffer, 0, BUFFER_SIZE);
fflush(stdout);
f = fopen(stdoutFileName.c_str(), "r");
if (f == nullptr)
return nullptr;

char* ptr = stdoutBuffer;
do {
ptr += strlen(ptr);
ptr = fgets(ptr, BUFFER_SIZE, f);
} while (ptr != nullptr);
fclose(f);

return stdoutBuffer;
}
Copy link
Owner

Choose a reason for hiding this comment

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

We should introduce a callback to get access to the output of printf from unit tests. As discussed, I want to make this standard in a future version of OpenCL, similarly to how we've done it in the cl_arm_printf extension.

if (m_kernel->program()->uses_printf()) {
// Create and initialize the printf buffer
auto buffer = m_queue->get_or_create_printf_buffer();
auto err = m_queue->reset_printf_buffer();
Copy link
Owner

Choose a reason for hiding this comment

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

This means we can be writing to the printf buffer concurrently to executing kernels (or maybe even the post-action code) with no protection whatsoever.

@kpet kpet mentioned this pull request Jul 16, 2023
4 tasks
@kpet
Copy link
Owner

kpet commented Jul 16, 2023

I've created #578 to track further work.

@kpet kpet merged commit 9387df0 into kpet:main Jul 16, 2023
9 checks passed
@rjodinchr rjodinchr deleted the pr/printf branch July 17, 2023 06:22
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