Skip to content

Commit 1dad1a1

Browse files
committed
WIP: ENH: Add ITK-Wasm benchmark interfaces
1 parent f5104d0 commit 1dad1a1

17 files changed

+5691
-83
lines changed

.gitignore

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,3 +42,11 @@ cmake-build*/**
4242
doc/*.pyg
4343
doc/_minted-ITKPerformanceBenchmarking/*
4444

45+
46+
emscripten-build/
47+
micromamba/
48+
node_modules/
49+
test/pyodide-emscripten.tar.bz2
50+
wasi-build/
51+
wasm/typescript/
52+
wasm/python/

CMakeLists.txt

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,38 +3,42 @@ cmake_minimum_required(VERSION 3.16.3)
33
if(NOT CMAKE_CXX_STANDARD)
44
set(CMAKE_CXX_STANDARD 17) # Supported values are ``14``, ``17`` and ``20``.
55
endif()
6+
67
if(NOT CMAKE_CXX_STANDARD_REQUIRED)
78
set(CMAKE_CXX_STANDARD_REQUIRED ON)
89
endif()
10+
911
if(NOT CMAKE_CXX_EXTENSIONS)
1012
set(CMAKE_CXX_EXTENSIONS OFF)
1113
endif()
1214

13-
## If building external to ITK, we need to capture
14-
## required build setting from ITK prior to calling
15-
## project()
15+
# # If building external to ITK, we need to capture
16+
# # required build setting from ITK prior to calling
17+
# # project()
1618
if(NOT ITK_SOURCE_DIR)
1719
find_package(ITK REQUIRED)
1820
list(APPEND CMAKE_MODULE_PATH ${ITK_CMAKE_DIR})
1921

2022
foreach(p
21-
## Only policies introduced after the cmake_minimum_required
22-
## version need to explicitly be set to NEW.
23-
# currently empty
24-
)
23+
24+
# # Only policies introduced after the cmake_minimum_required
25+
# # version need to explicitly be set to NEW.
26+
# currently empty
27+
)
2528
if(POLICY ${p})
2629
cmake_policy(SET ${p} NEW)
2730
endif()
2831
endforeach()
2932

30-
3133
# Set a default build type if none was specified
3234
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
3335
message(STATUS "Setting build type to 'Release' as none was specified.")
3436
set(CMAKE_BUILD_TYPE Release CACHE STRING "Choose the type of build." FORCE)
37+
3538
# Set the possible values of build type for cmake-gui
3639
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release" "MinSizeRel" "RelWithDebInfo")
3740
endif()
41+
3842
enable_language(C)
3943
enable_language(CXX)
4044
endif()
@@ -44,10 +48,16 @@ project(PerformanceBenchmarking)
4448
set(PerformanceBenchmarking_LIBRARIES PerformanceBenchmarking)
4549

4650
include_directories(${CMAKE_BINARY_DIR})
51+
4752
if(NOT ITK_SOURCE_DIR)
4853
include(ITKModuleExternal)
54+
55+
if(WASI OR EMSCRIPTEN)
56+
set(BENCHMARK_USE_ITKWasm CACHE BOOL "Build with ITK-Wasm interface." ON)
57+
endif()
4958
else()
5059
set(ITK_DIR ${CMAKE_BINARY_DIR})
5160
itk_module_impl()
5261
endif()
62+
5363
add_subdirectory(examples)

environment.yml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
name: performance-benchmarking
2+
channels:
3+
- conda-forge
4+
dependencies:
5+
- pytest
6+
- pytest-benchmark
7+
- python=3.11
8+
- pip
9+
- pip:
10+
- hatch
11+
- itkwasm-mesh-io
12+
- itkwasm-image-io

examples/CMakeLists.txt

Lines changed: 27 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,21 @@
1-
cmake_minimum_required(VERSION 3.10.2)
1+
cmake_minimum_required(VERSION 3.16.2)
22
project(ITKBenchmarks NONE)
33

4+
option(BENCHMARK_USE_ITKWasm "Enable ITK-Wasm performance benchmarking interfaces" OFF)
5+
set(_itkwasm_deps)
6+
7+
if(BENCHMARK_USE_ITKWasm)
8+
list(APPEND _itkwasm_deps WebAssemblyInterface)
9+
add_definitions(-DPERFORMANCE_BENCHMARKING_USE_ITKWASM)
10+
endif()
11+
412
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/CMake ${CMAKE_MODULE_PATH})
513
include(ITKBenchmarksExternalData)
614

715
ExternalData_Expand_Arguments(ITKBenchmarksData
816
BRAIN_IMAGE
917
"DATA{Data/Input/brainweb165a10f17.mha}"
10-
)
18+
)
1119
cmake_host_system_information(RESULT HOSTNAME QUERY HOSTNAME)
1220
string(TOLOWER "${HOSTNAME}" HOSTNAME_LOWER)
1321
set(TEST_OUTPUT_DIR "${PROJECT_BINARY_DIR}/Testing")
@@ -16,24 +24,29 @@ file(MAKE_DIRECTORY ${BENCHMARK_RESULTS_OUTPUT_DIR})
1624

1725
include(CTest)
1826

27+
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
28+
1929
option(BENCHMARK_ITK_CORE "Test the performance of ITK Core." ON)
30+
2031
if(BENCHMARK_ITK_CORE)
2132
add_subdirectory(Core)
2233
endif()
2334

24-
option(BENCHMARK_ITK_FILTERING "Test the performance of ITK Filters." ON)
25-
if(BENCHMARK_ITK_FILTERING)
26-
add_subdirectory(Filtering)
27-
endif()
35+
# option(BENCHMARK_ITK_FILTERING "Test the performance of ITK Filters." ON)
2836

29-
option(BENCHMARK_ITK_REGISTRATION "Test the performance of ITK Registration." ON)
30-
if(BENCHMARK_ITK_REGISTRATION)
31-
add_subdirectory(Registration)
32-
endif()
37+
# if(BENCHMARK_ITK_FILTERING)
38+
# add_subdirectory(Filtering)
39+
# endif()
3340

34-
option(BENCHMARK_ITK_SEGMENTATION "Test the performance of ITK Segmentation." ON)
35-
if(BENCHMARK_ITK_SEGMENTATION)
36-
add_subdirectory(Segmentation)
37-
endif()
41+
# option(BENCHMARK_ITK_REGISTRATION "Test the performance of ITK Registration." ON)
42+
43+
# if(BENCHMARK_ITK_REGISTRATION)
44+
# add_subdirectory(Registration)
45+
# endif()
46+
47+
# option(BENCHMARK_ITK_SEGMENTATION "Test the performance of ITK Segmentation." ON)
3848

49+
# if(BENCHMARK_ITK_SEGMENTATION)
50+
# add_subdirectory(Segmentation)
51+
# endif()
3952
ExternalData_Add_Target(ITKBenchmarksData)

examples/Core/CMakeLists.txt

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,20 @@ project(ITKBenchmarkCore)
22

33
find_package(ITK REQUIRED
44
COMPONENTS
5-
PerformanceBenchmarking
6-
ITKCommon
7-
)
5+
PerformanceBenchmarking
6+
ITKCommon
7+
${_itkwasm_deps}
8+
)
89
include(${ITK_USE_FILE})
910

10-
11-
add_executable(ThreadOverheadBenchmark ThreadOverhead.cxx )
12-
target_link_libraries(ThreadOverheadBenchmark ${ITK_LIBRARIES})
11+
add_executable(thread-overhead thread-overhead.cxx)
12+
target_link_libraries(thread-overhead PUBLIC ${ITK_LIBRARIES})
1313
add_test(
14-
NAME ThreadOverheadBenchmark
15-
COMMAND ThreadOverheadBenchmark
16-
${BENCHMARK_RESULTS_OUTPUT_DIR}/__DATESTAMP__ThreadOverheadBenchmark.json
17-
1000 )
18-
set_property(TEST ThreadOverheadBenchmark APPEND PROPERTY LABELS Core)
19-
## performance tests should not be run in parallel
20-
set_tests_properties(ThreadOverheadBenchmark PROPERTIES RUN_SERIAL TRUE)
14+
NAME thread-overhead-benchmark
15+
COMMAND thread-overhead
16+
${BENCHMARK_RESULTS_OUTPUT_DIR}/__DATESTAMP__thread-overhead.json
17+
--iterations 1000)
18+
set_property(TEST thread-overhead-benchmark APPEND PROPERTY LABELS Core)
19+
20+
# # performance tests should not be run in parallel
21+
set_tests_properties(thread-overhead-benchmark PROPERTIES RUN_SERIAL TRUE)

examples/Core/ThreadOverhead.cxx renamed to examples/Core/thread-overhead.cxx

Lines changed: 41 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,11 @@
2222
#include "itkHighPriorityRealTimeProbe.h"
2323
#include "itkHighPriorityRealTimeProbesCollector.h"
2424

25+
#if defined(PERFORMANCE_BENCHMARKING_USE_ITKWASM)
26+
# include "itkPipeline.h"
27+
# include "itkOutputTextStream.h"
28+
#endif
29+
2530
#include <sstream>
2631
#include <fstream>
2732
#include "PerformanceBenchmarkingUtilities.h"
@@ -122,16 +127,46 @@ time_it(unsigned int threads, unsigned int iterations)
122127
int
123128
main(int argc, char * argv[])
124129
{
125-
if (argc > 3)
130+
bool noPrintStdout = false;
131+
bool expandedReport = false;
132+
bool noPrintSystemInfo = false;
133+
bool noPrintReportHead = false;
134+
constexpr int iterationsDefault = 500;
135+
const int threadsDefault = MultiThreaderName::GetGlobalDefaultNumberOfThreads();
136+
137+
#if defined(PERFORMANCE_BENCHMARKING_USE_ITKWASM)
138+
itk::wasm::Pipeline pipeline("thread-overhead", "Estimate the overhead cost per-thread.", argc, argv);
139+
140+
itk::wasm::OutputTextStream timingsJson;
141+
pipeline.add_option("timings", timingsJson, "Internal timings")->type_name("OUTPUT_JSON");
142+
143+
pipeline.add_flag("--no-print-stdout", noPrintStdout, "Do not print to stdout.");
144+
pipeline.add_flag("--expanded-report", expandedReport, "Print an expanded report.");
145+
pipeline.add_flag("--no-print-system-info", noPrintSystemInfo, "Do not print system information.");
146+
pipeline.add_flag("--no-print-report-head", noPrintReportHead, "Do not print the report header.");
147+
148+
int iterations = iterationsDefault;
149+
pipeline.add_option("--iterations", iterations, "Number of iterations to run.");
150+
151+
int threads = threadsDefault;
152+
pipeline.add_option("--threads", threads, "Number of threads to use.");
153+
154+
ITK_WASM_PARSE(pipeline);
155+
156+
std::ostream & timingsStream = timingsJson.Get();
157+
#else
158+
if (argc > 5)
126159
{
127160
std::cerr << "Usage: " << std::endl;
128-
std::cerr << argv[0] << " timingsFile [iterations [threads]]" << std::endl;
161+
std::cerr << argv[0] << " timingsFile [--iterations iterations [--threads threads]]" << std::endl;
129162
return EXIT_FAILURE;
130163
}
131164

132165
const std::string timingsFileName = ReplaceOccurrence(argv[1], "__DATESTAMP__", PerfDateStamp());
133-
const int iterations = (argc > 2) ? std::stoi(argv[2]) : 500;
134-
const int threads = (argc > 3) ? std::stoi(argv[3]) : MultiThreaderName::GetGlobalDefaultNumberOfThreads();
166+
auto timingsStream = std::ofstream(timingsFileName, std::ios_base::out);
167+
const int iterations = (argc > 3) ? std::stoi(argv[3]) : iterationsDefault;
168+
const int threads = (argc > 5) ? std::stoi(argv[5]) : threadsDefault;
169+
#endif
135170

136171
if (threads == 1)
137172
{
@@ -142,7 +177,8 @@ main(int argc, char * argv[])
142177
ProbeType t1 = time_it(1, iterations);
143178
ProbeType t2 = time_it(threads, iterations);
144179

145-
WriteExpandedReport(timingsFileName, collector, true, true, false);
180+
WriteExpandedReport(
181+
timingsStream, collector, !noPrintStdout, expandedReport, !noPrintSystemInfo, !noPrintReportHead, false);
146182

147183
double cost = (t2.GetMinimum() - t1.GetMinimum()) / (threads - 1.0);
148184

include/PerformanceBenchmarkingUtilities.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,14 +25,16 @@ PerformanceBenchmarking_EXPORT std::string
2525
PerfDateStamp();
2626

2727
PerformanceBenchmarking_EXPORT std::string
28-
ReplaceOccurrence(std::string str, const std::string && findvalue, const std::string && replacevalue);
28+
ReplaceOccurrence(std::string str, const std::string && findvalue, const std::string && replacevalue);
2929

3030
PerformanceBenchmarking_EXPORT std::string
3131
DecorateWithBuildInformation(std::string inputJson);
3232

3333
PerformanceBenchmarking_EXPORT void
34-
WriteExpandedReport(const std::string & timingsFileName,
34+
WriteExpandedReport(std::ostream & timingsStream,
3535
itk::HighPriorityRealTimeProbesCollector & collector,
36+
bool printStdout,
37+
bool expandedReport,
3638
bool printSystemInfo,
3739
bool printReportHead,
3840
bool useTabs);

itk-module.cmake

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,9 @@ For more information, see::
1616
itk_module(PerformanceBenchmarking
1717
ENABLE_SHARED
1818
PRIVATE_DEPENDS
19-
ITKCommon
19+
ITKCommon
2020
TEST_DEPENDS
21-
ITKTestKernel
21+
ITKTestKernel
2222
EXCLUDE_FROM_DEFAULT
2323
DESCRIPTION
2424
"${DOCUMENTATION}"

package.json

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
{
2+
"name": "@itk-wasm/performance-benchmarking-build",
3+
"version": "1.0.0",
4+
"description": "npm scripts to generate itk-wasm artifacts.",
5+
"private": true,
6+
"packageManager": "pnpm@9.1.1",
7+
"type": "module",
8+
"itk-wasm": {
9+
"emscripten-docker-image": "itkwasm/emscripten:20240517-32a1ffd9",
10+
"wasi-docker-image": "itkwasm/wasi:20240517-32a1ffd9",
11+
"typescript-package-name": "@itk-wasm/performance-benchmarking",
12+
"typescript-output-dir": "wasm/typescript",
13+
"python-package-name": "itkwasm-performance-benchmarking",
14+
"python-output-dir": "wasm/python",
15+
"package-description": "Benchmark ITK performance.",
16+
"repository": "https://github.com/InsightSoftwareConsortium/ITKPerformanceBenchmarking"
17+
},
18+
"scripts": {
19+
"build": "pnpm build:gen:typescript && pnpm -r build && pnpm build:gen:python",
20+
"build:emscripten": "itk-wasm pnpm-script build:emscripten",
21+
"build:emscripten:debug": "itk-wasm pnpm-script build:emscripten:debug",
22+
"build:wasi": "itk-wasm pnpm-script build:wasi",
23+
"build:wasi:debug": "itk-wasm pnpm-script build:wasi:debug",
24+
"build:python:wasi": "itk-wasm pnpm-script build:python:wasi",
25+
"bindgen:typescript": "itk-wasm pnpm-script bindgen:typescript",
26+
"bindgen:python": "itk-wasm pnpm-script bindgen:python",
27+
"build:gen:typescript": "itk-wasm pnpm-script build:gen:typescript",
28+
"build:gen:python": "itk-wasm pnpm-script build:gen:python",
29+
"build:micromamba": "itk-wasm pnpm-script build:micromamba",
30+
"build:python:versionSync": "itk-wasm pnpm-script build:python:versionSync",
31+
"publish:python": "itk-wasm pnpm-script publish:python",
32+
"test": "pnpm test:data:download && pnpm -r test && pnpm test:python",
33+
"test:data:download": "echo \"not needed\"",
34+
"test:data:pack": "dam pack test/data test/data.tar.gz",
35+
"test:python:wasi": "itk-wasm pnpm-script test:python:wasi",
36+
"test:python:emscripten": "itk-wasm pnpm-script test:python:emscripten",
37+
"test:python:dispatch": "itk-wasm pnpm-script test:python:dispatch",
38+
"test:python": "itk-wasm pnpm-script test:python",
39+
"test:wasi": "itk-wasm pnpm-script test:wasi -- -V",
40+
"clean": "git clean -fdx -e node_modules"
41+
},
42+
"license": "Apache-2.0",
43+
"devDependencies": {
44+
"@itk-wasm/dam": "^1.1.1",
45+
"@thewtex/setup-micromamba": "^1.9.7",
46+
"itk-wasm": "^1.0.0-b.175"
47+
}
48+
}

0 commit comments

Comments
 (0)