CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
190 lines
6.2 KiB
C++
190 lines
6.2 KiB
C++
/* Copyright (c) Advanced Micro Devices, Inc. All rights reserved.
|
|
*
|
|
* SPDX-License-Identifier: MIT
|
|
*/
|
|
|
|
/* no-odirect-write - Write a registered GPU buffer to a file the caller opened
|
|
* without O_DIRECT. hipFile does not require O_DIRECT on the caller's fd: on an
|
|
* O_DIRECT-capable filesystem it transparently reopens the file with O_DIRECT
|
|
* and still takes the fast GPU-direct path; only when the filesystem cannot do
|
|
* O_DIRECT does it use the POSIX compat fallback.
|
|
*
|
|
* Usage: ./no-odirect-write OUTPUT [GPUID]
|
|
*
|
|
* OUTPUT Path to the output file. Created/truncated. Receives NOW_SIZE
|
|
* (default 128 KiB) bytes of generated test pattern. The file is
|
|
* opened without O_DIRECT; hipFile decides fast path vs. compat
|
|
* fallback based on the filesystem.
|
|
* GPUID GPU device index (optional, default 0).
|
|
*
|
|
* Steps:
|
|
* 1. Select GPU
|
|
* 2. Build CPU pattern + copy to GPU
|
|
* 3. hipFileBufRegister
|
|
* 4. open file without O_DIRECT + hipFileHandleRegister
|
|
* 5. hipFileWrite (fast path via hipFile's internal O_DIRECT reopen on an
|
|
* O_DIRECT-capable filesystem; POSIX compat fallback otherwise)
|
|
* 6. ftruncate to exact size
|
|
* 7. Hash verify
|
|
*
|
|
* No env var is needed. The compat fallback is enabled by default and is only
|
|
* exercised on a filesystem that cannot do O_DIRECT; set
|
|
* HIPFILE_ALLOW_COMPAT_MODE=true only if you previously disabled it (and are
|
|
* running on such a filesystem).
|
|
*/
|
|
|
|
#include "examples_common.h"
|
|
|
|
#include <hipfile.h>
|
|
#include <hip/hip_runtime_api.h>
|
|
|
|
#include <cerrno>
|
|
#include <fcntl.h>
|
|
#include <cinttypes>
|
|
#include <cstdint>
|
|
#include <cstdio>
|
|
#include <cstdlib>
|
|
#include <cstring>
|
|
#include <sys/stat.h>
|
|
#include <sys/types.h>
|
|
#include <unistd.h>
|
|
|
|
/// @brief Size of the test payload in bytes. Override at compile time.
|
|
#ifndef NOW_SIZE
|
|
#define NOW_SIZE (128UL * 1024UL)
|
|
#endif
|
|
|
|
int
|
|
main(int argc, char *argv[])
|
|
{
|
|
if (argc < 2 || argc > 3) {
|
|
fprintf(stderr, "Usage: %s OUTPUT [GPUID]\n", argv[0]);
|
|
return EXIT_FAILURE;
|
|
}
|
|
|
|
const char *out_path = argv[1];
|
|
const int gpu_id = (argc == 3) ? atoi(argv[2]) : 0;
|
|
const size_t payload_size = NOW_SIZE;
|
|
const size_t alloc_size = align_up(payload_size, BLOCK_ALIGN);
|
|
|
|
int out_fd = -1;
|
|
hipFileHandle_t out_handle;
|
|
void *devbuf = NULL;
|
|
uint8_t *cpu_pattern = NULL;
|
|
bool buf_registered = false;
|
|
int exit_status = EXIT_FAILURE;
|
|
hipError_t hip_err;
|
|
hipFileError_t hipfile_err;
|
|
ssize_t nbytes;
|
|
|
|
/* 1. Select GPU */
|
|
hip_err = hipSetDevice(gpu_id);
|
|
if (hipSuccess != hip_err) {
|
|
fprintf(stderr, "Could not select GPU %d (%d)\n", gpu_id, hip_err);
|
|
return EXIT_FAILURE;
|
|
}
|
|
|
|
/* 2. Build CPU pattern + copy to GPU */
|
|
cpu_pattern = static_cast<uint8_t *>(malloc(payload_size));
|
|
if (!cpu_pattern) {
|
|
fprintf(stderr, "Could not allocate CPU pattern buffer\n");
|
|
return EXIT_FAILURE;
|
|
}
|
|
fill_pattern(cpu_pattern, payload_size);
|
|
|
|
hip_err = hipMalloc(&devbuf, alloc_size);
|
|
if (hipSuccess != hip_err) {
|
|
fprintf(stderr, "Could not allocate %zu bytes on GPU %d (%d)\n", alloc_size, gpu_id, hip_err);
|
|
goto free_cpu_pattern;
|
|
}
|
|
|
|
hip_err = hipMemcpy(devbuf, cpu_pattern, payload_size, hipMemcpyHostToDevice);
|
|
if (hipSuccess != hip_err) {
|
|
fprintf(stderr, "hipMemcpy to device failed (%d)\n", hip_err);
|
|
goto free_devbuf;
|
|
}
|
|
|
|
/* 3. hipFileBufRegister */
|
|
hipfile_err = hipFileBufRegister(devbuf, alloc_size, 0);
|
|
if (hipFileSuccess != hipfile_err.err) {
|
|
fprintf(stderr, "Buffer register failed (%s)\n", hipFileGetOpErrorString(hipfile_err.err));
|
|
goto free_devbuf;
|
|
}
|
|
buf_registered = true;
|
|
|
|
/* 4. open file WITHOUT O_DIRECT + hipFileHandleRegister */
|
|
if (open_file(out_path, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH, &out_fd,
|
|
&out_handle)) {
|
|
goto deregister_buf;
|
|
}
|
|
|
|
/* 5. hipFileWrite via POSIX fallback.
|
|
* Without O_DIRECT there is no transfer-size alignment requirement, so we
|
|
* can write the exact payload size. */
|
|
nbytes = hipFileWrite(out_handle, devbuf, payload_size, /*file_offset=*/0,
|
|
/*buffer_offset=*/0);
|
|
if (nbytes < 0) {
|
|
fprintf(stderr, "Could not write to %s (%zd) (%s)\n", out_path, nbytes,
|
|
IS_HIPFILE_ERR(nbytes) ? HIPFILE_ERRSTR(nbytes) : strerror(errno));
|
|
goto close_out;
|
|
}
|
|
|
|
/* 6. ftruncate to exact size (defensive; no-op when we wrote payload_size exactly) */
|
|
if (-1 == ftruncate(out_fd, static_cast<off_t>(payload_size))) {
|
|
fprintf(stderr, "Could not truncate %s (%s)\n", out_path, strerror(errno));
|
|
goto close_out;
|
|
}
|
|
|
|
if (close_file(out_path, out_fd, out_handle)) {
|
|
out_fd = -1;
|
|
goto deregister_buf;
|
|
}
|
|
out_fd = -1;
|
|
|
|
/* 7. Hash verify */
|
|
{
|
|
uint64_t hash_pattern = hash_buffer(cpu_pattern, payload_size);
|
|
uint64_t hash_written;
|
|
|
|
if (hash_file_range(out_path, 0, payload_size, &hash_written))
|
|
goto deregister_buf;
|
|
|
|
if (hash_pattern != hash_written) {
|
|
fprintf(stderr, "Hash mismatch: pattern=0x%016" PRIx64 " %s=0x%016" PRIx64 "\n", hash_pattern,
|
|
out_path, hash_written);
|
|
goto deregister_buf;
|
|
}
|
|
|
|
printf("OK %s (%zu bytes, hash 0x%016" PRIx64 ")\n", out_path, payload_size, hash_pattern);
|
|
}
|
|
|
|
exit_status = EXIT_SUCCESS;
|
|
|
|
close_out:
|
|
if (out_fd != -1) {
|
|
if (close_file(out_path, out_fd, out_handle))
|
|
exit_status = EXIT_FAILURE;
|
|
}
|
|
|
|
deregister_buf:
|
|
if (buf_registered) {
|
|
hipfile_err = hipFileBufDeregister(devbuf);
|
|
if (hipFileSuccess != hipfile_err.err) {
|
|
fprintf(stderr, "Buffer deregister failed (%s)\n", hipFileGetOpErrorString(hipfile_err.err));
|
|
exit_status = EXIT_FAILURE;
|
|
}
|
|
}
|
|
|
|
free_devbuf:
|
|
hip_err = hipFree(devbuf);
|
|
if (hipSuccess != hip_err) {
|
|
fprintf(stderr, "Could not free device buffer (%d)\n", hip_err);
|
|
exit_status = EXIT_FAILURE;
|
|
}
|
|
|
|
free_cpu_pattern:
|
|
free(cpu_pattern);
|
|
|
|
return exit_status;
|
|
}
|