Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,5 @@ dto-test*
libdto.so*
build*/
tests/baselines*/
dtoctl
/doc/dtoctl.1
27 changes: 27 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,33 @@ if (HAS_WAITPKG)
target_compile_options(dto PRIVATE -mwaitpkg -march=native)
endif()

# Build dtoctl with a default preload path matching the library installation.
get_filename_component(DTOCTL_LIBDIR "${CMAKE_INSTALL_LIBDIR}" ABSOLUTE
BASE_DIR "${CMAKE_INSTALL_PREFIX}")
set(DTOCTL_LIBPATH "${DTOCTL_LIBDIR}/libdto.so" CACHE FILEPATH
"Path to libdto.so that dtoctl prepends to LD_PRELOAD")
add_executable(dtoctl dtoctl.c)
target_compile_definitions(dtoctl PRIVATE LIBDTO_PATH="${DTOCTL_LIBPATH}")
install(TARGETS dtoctl RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})

# Build and install the optional section 1 manual.
find_program(PANDOC_EXECUTABLE NAMES pandoc)
if(PANDOC_EXECUTABLE)
set(DTOCTL_MAN_PAGE "${CMAKE_CURRENT_BINARY_DIR}/doc/dtoctl.1")
add_custom_command(
OUTPUT "${DTOCTL_MAN_PAGE}"
COMMAND ${CMAKE_COMMAND} -E make_directory "${CMAKE_CURRENT_BINARY_DIR}/doc"
COMMAND "${PANDOC_EXECUTABLE}" --standalone --to=man
"${CMAKE_CURRENT_SOURCE_DIR}/doc/dtoctl.md" -o "${DTOCTL_MAN_PAGE}"
DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/doc/dtoctl.md"
COMMENT "Generating dtoctl(1) manual"
VERBATIM)
add_custom_target(dtoctl-man ALL DEPENDS "${DTOCTL_MAN_PAGE}")
install(FILES "${DTOCTL_MAN_PAGE}" DESTINATION ${CMAKE_INSTALL_MANDIR}/man1)
else()
message(STATUS "Skipping dtoctl manual generation and installation: install pandoc to build the man page.")
endif()

# Build dto-test and dto-test-wodto
add_executable(dto-test dto-test.c)
target_link_libraries(dto-test PRIVATE DTO::dto pthread)
Expand Down
34 changes: 31 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,47 @@
#
# SPDX-License-Identifier: MIT

all: libdto dto-test-wodto
all: libdto dtoctl dto-test-wodto man

.PHONY: man install-man

DML_LIB_CXX=-D_GNU_SOURCE

# Path to libdto.so that dtoctl prepends to LD_PRELOAD (matches "make install").
DTOCTL_LIBPATH ?= /usr/lib64/libdto.so
PANDOC ?= pandoc
MANDIR ?= /usr/share/man

libdto: dto.c
gcc -shared -fPIC -Wl,-soname,libdto.so dto.c $(DML_LIB_CXX) -DDTO_STATS_SUPPORT -DDTO_ACCEL_CONFIG_SUPPORT -DDTO_NUMA_SUPPORT -o libdto.so.1.0 -laccel-config -ldl -lnuma -mwaitpkg

libdto_nostats: dto.c
gcc -shared -fPIC -Wl,-soname,libdto.so dto.c $(DML_LIB_CXX) -DDTO_ACCEL_CONFIG_SUPPORT -DDTO_NUMA_SUPPORT -o libdto.so.1.0 -laccel-config -ldl -lnuma -mwaitpkg

install:
dtoctl: dtoctl.c
gcc -O2 -Wall dtoctl.c -DLIBDTO_PATH=\"$(DTOCTL_LIBPATH)\" -o dtoctl

man: doc/dtoctl.1

doc/dtoctl.1: doc/dtoctl.md
@if command -v "$(PANDOC)" >/dev/null 2>&1; then \
"$(PANDOC)" --standalone --to=man $< -o $@; \
else \
echo "Skipping dtoctl manual generation: install pandoc to build the man page."; \
fi

install: install-man
cp libdto.so.1.0 /usr/lib64/
ln -sf /usr/lib64/libdto.so.1.0 /usr/lib64/libdto.so.1
ln -sf /usr/lib64/libdto.so.1.0 /usr/lib64/libdto.so
cp dtoctl /usr/bin/

install-man: man
@if [ -f doc/dtoctl.1 ]; then \
install -D -m 644 doc/dtoctl.1 "$(MANDIR)/man1/dtoctl.1"; \
else \
echo "Skipping dtoctl manual installation: no generated man page is available."; \
fi

install-local:
ln -sf ./libdto.so.1.0 ./libdto.so.1
Expand All @@ -28,4 +55,5 @@ dto-test-wodto: dto-test.c
gcc -g dto-test.c $(DML_LIB_CXX) -o dto-test-wodto -lpthread

clean:
rm -rf *.o *.so dto-test
rm -rf *.o *.so dto-test dtoctl
rm -f doc/dtoctl.1
Comment on lines 57 to +59
33 changes: 33 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,39 @@ Although not the only usage models of DTO, the following are some common ones:
DTO_WAIT_METHOD=yield or umwait (saves either cycles or power)


## Using dtoctl

Setting `LD_PRELOAD` and exporting the `DTO_*` environment variables by hand is
error prone. The `dtoctl` tool provides a simpler interface: it takes the DTO
settings as command line options, converts them to the corresponding `DTO_*`
environment variables, prepends `libdto.so` to `LD_PRELOAD`, and then runs the
target program. For example, instead of

```bash
export LD_PRELOAD=/usr/local/lib/libdto.so
export DTO_WAIT_METHOD=busypoll
export DTO_CPU_SIZE_FRACTION=0.33
export DTO_AUTO_ADJUST_KNOBS=1
./prog
```

you can run

```bash
dtoctl -w busypoll -c 0.33 ./prog
```

Every environment variable listed above has a corresponding option, and only the
options you pass are applied: a `DTO_*` variable you already exported is left
untouched, and an explicit option overrides it. The `libdto.so` path is resolved
from `-l/--library`, then `$DTO_LIBRARY`, then the compiled-in default
(`/usr/local/lib/libdto.so` for a CMake build, `/usr/lib64/libdto.so` for the
Makefile build), and is prepended to any existing `LD_PRELOAD`.

Run `dtoctl --help` for the option list, or `man 1 dtoctl` for the full manual,
which documents each option and gives a ready-to-run command for each of the
usage models above.

## Build

Pre-requisite packages:
Expand Down
181 changes: 181 additions & 0 deletions doc/dtoctl.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
% DTOCTL(1) Dtoctl User Manuals
% Honggyu Kim <honggyu.kim@sk.com>
% 2026

NAME
====
dtoctl - run a program with DSA Transparent Offload (DTO) preloaded


SYNOPSIS
========
dtoctl [_options_] COMMAND [_command-options_]


DESCRIPTION
===========
The **dtoctl** tool runs `COMMAND` with the DSA Transparent Offload library
(**libdto.so**) preloaded, so that its `memcpy`, `memmove`, `memset`, and
`memcmp` calls are transparently offloaded to Intel DSA (Data Streaming
Accelerator).

Without **dtoctl**, users must set **LD_PRELOAD** to point at **libdto.so** and
export a set of **DTO_\*** environment variables to control DTO behavior.
**dtoctl** replaces that manual setup: it converts its command line options into
the corresponding **DTO_\*** environment variables, prepends **libdto.so** to
**LD_PRELOAD**, and then executes `COMMAND`.

Only the options that are explicitly given are applied. Options that are not
given leave any pre-existing **DTO_\*** environment variables (or the DTO
built-in defaults) untouched, and an explicitly given option overrides a
previously exported variable of the same name.


LIBRARY RESOLUTION
==================
The path of **libdto.so** to preload is resolved in the following order:

1. The `-l`, `--library` option, if given.
2. The **DTO_LIBRARY** environment variable, if set.
3. The compiled-in default path (`/usr/local/lib/libdto.so` for a default
CMake build, or `/usr/lib64/libdto.so` for the Makefile build).

The resolved path is prepended to any existing **LD_PRELOAD** value.


OPTIONS
=======

Library
-------
-l _PATH_, \--library=_PATH_
: Path to **libdto.so** to prepend to **LD_PRELOAD**. Overrides
**DTO_LIBRARY** and the compiled-in default.
Default: the compiled-in library path (see LIBRARY RESOLUTION).

Offload tuning
--------------
-w _METHOD_, \--wait-method=_METHOD_
: How to wait for DSA completion: _yield_, _busypoll_, _umwait_, or _tpause_.
Sets **DTO_WAIT_METHOD**. Default: _busypoll_.

-b _BYTES_, \--min-bytes=_BYTES_
: Minimum operation size offloaded to DSA. Smaller operations run on the CPU.
Sets **DTO_MIN_BYTES**. Default: 65536.

-c _FRACTION_, \--cpu-fraction=_FRACTION_
: Fraction (0.0 <= f < 1.0) of each operation performed on the CPU in parallel
to DSA. Sets **DTO_CPU_SIZE_FRACTION**. Default: 0.0.

-n _MODE_, \--numa-aware=_MODE_
: NUMA awareness: _0_ disable, _1_ buffer-centric, _2_ cpu-centric.
Sets **DTO_IS_NUMA_AWARE**. Default: _0_.

-q _LIST_, \--wq-list=_LIST_
: Semicolon-separated list of DSA work queues to use, e.g. "wq0.0;wq2.0".
Names must match those under /dev/dsa/. Sets **DTO_WQ_LIST**.
Default: auto-discover all available WQs.

\--umwait-delay=_CYCLES_
: Delay in cycles for the umwait instruction. Sets **DTO_UMWAIT_DELAY**.
Default: 100000.

\--overlapping-memmove=_WHERE_
: Where to run memmove with overlapping buffers: _cpu_ or _dsa_.
Sets **DTO_OVERLAPPING_MEMMOVE_ACTION** (cpu -> 0, dsa -> 1). Default: _cpu_.

Disable DSA offload for specific operations
-------------------------------------------
By default every one of these operations is offloaded to DSA; each option below
turns a single one back into its standard C library call on the CPU.

\--no-memcpy
: Use the system memcpy instead of DSA. Sets **DTO_DSA_MEMCPY=0**.

\--no-memmove
: Use the system memmove instead of DSA. Sets **DTO_DSA_MEMMOVE=0**.

\--no-memset
: Use the system memset instead of DSA. Sets **DTO_DSA_MEMSET=0**.

\--no-memcmp
: Use the system memcmp instead of DSA. Sets **DTO_DSA_MEMCMP=0**.

Other toggles
-------------
\--no-cache-control
: Clear the DSA cache control flag to avoid cache pollution.
Sets **DTO_DSA_CC=0**. Default: cache control is on.

\--no-auto-adjust
: Disable auto tuning of cpu-fraction and min-bytes.
Sets **DTO_AUTO_ADJUST_KNOBS=0**. Default: auto tuning is on.

\--stdc-only
: Use only the standard C memory functions, no DSA offload.
Sets **DTO_USESTDC_CALLS=1**. Default: DSA offload is enabled.

Statistics and logging
----------------------
\--stats
: Enable stats collection. For debugging/profiling only, as it slows down the
workload. Sets **DTO_COLLECT_STATS=1**. Default: off.

\--stats-file=_PATH_
: Write the stats histogram to _PATH_ instead of standard output.
Sets **DTO_STATS_FILE**. Default: standard output.

\--log-file=_PATH_
: Redirect DTO output to _PATH_ (the file name is suffixed by the pid).
Sets **DTO_LOG_FILE**. Default: standard output.

\--log-level=_LEVEL_
: Verbosity of DTO logging: _0_, _1_, or _2_. Sets **DTO_LOG_LEVEL**.
Default: _0_.

-?, \--help
: Print help message and list of options with description.

\--usage
: Print usage string.


EXAMPLES
========
Run a program with DTO using the installed **libdto.so**:

$ dtoctl ./prog

The equivalent of the manual setup

$ export LD_PRELOAD=/usr/lib64/libdto.so
$ export DTO_WAIT_METHOD=busypoll
$ export DTO_CPU_SIZE_FRACTION=0.33
$ export DTO_AUTO_ADJUST_KNOBS=1
$ ./prog

becomes a single command:

$ dtoctl -w busypoll -c 0.33 ./prog

Latency reduction mode (auto tuning on, busy polling):

$ dtoctl -w busypoll ./prog

Power reduction mode (offload everything to DSA, wait with umwait):

$ dtoctl -w umwait -c 0.0 --no-auto-adjust ./prog

Avoid cache pollution (offload everything, clear cache control):

$ dtoctl -w yield -c 0.0 --no-auto-adjust --no-cache-control ./prog

Use a locally built library and a specific set of work queues, and collect
stats:

$ dtoctl -l ./libdto.so.1.0 -q "wq0.0;wq2.0;wq4.0;wq6.0" --stats ./prog


SEE ALSO
========
**ld.so**(8)
Loading