Skip to content

threads build #1443

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

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
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: 1 addition & 1 deletion CITATION.cff
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ type: software
authors:
- given-names: Matthew
family-names: McCormick
email: matt@mmmccormick.com
email: matt@fideus.io
affiliation: 'Kitware, Inc'
orcid: 'https://orcid.org/0000-0001-9475-3756'
keywords:
Expand Down
2 changes: 1 addition & 1 deletion examples/debugging/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
"start": "http-server -o"
},
"type": "module",
"author": "Matt McCormick <matt@mmmccormick.com>",
"author": "Matt McCormick <matt@fideus.io>",
"license": "Apache-2.0",
"dependencies": {
"http-server": "^14.1.0",
Expand Down
2 changes: 1 addition & 1 deletion examples/different-input-types/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"test:wasi": "itk-wasm -b wasi-build run different-input-types.wasi.wasm -- ./Gourds.png label.png overlay.png",
"test:wasi:help": "itk-wasm -b wasi-build run different-input-types.wasi.wasm -- --help"
},
"author": "Matt McCormick <matt@mmmccormick.com>",
"author": "Matt McCormick <matt@fideus.io>",
"license": "Apache-2.0",
"dependencies": {
"itk-wasm": "workspace:^"
Expand Down
2 changes: 1 addition & 1 deletion examples/hello-pipeline/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
"test:quiet": "itk-wasm run wasi-build/hello-pipeline.wasi.wasm -- --quiet cthead1.png",
"test:help": "itk-wasm run wasi-build/hello-pipeline.wasi.wasm -- --help"
},
"author": "Matt McCormick <matt@mmmccormick.com>",
"author": "Matt McCormick <matt@fideus.io>",
"license": "Apache-2.0",
"dependencies": {
"fs-extra": "^10.0.0",
Expand Down
2 changes: 1 addition & 1 deletion examples/hello-world/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
"test:browser": "playwright test",
"test:browser:debug": "playwright test --debug"
},
"author": "Matt McCormick <matt@mmmccormick.com>",
"author": "Matt McCormick <matt@fideus.io>",
"license": "Apache-2.0",
"dependencies": {
"fs-extra": "^11.1.0",
Expand Down
2 changes: 1 addition & 1 deletion examples/inputs-outputs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
"test:wasi": "itk-wasm -i itkwasm/wasi:latest -b wasi-build run inputs-outputs.wasi.wasm -- -- cthead1.png smoothed.png",
"test:wasi:help": "itk-wasm -i itkwasm/wasi:latest -b wasi-build run inputs-outputs.wasi.wasm -- -- --help"
},
"author": "Matt McCormick <matt@mmmccormick.com>",
"author": "Matt McCormick <matt@fideus.io>",
"license": "Apache-2.0",
"devDependencies": {
"@itk-wasm/image-io": "workspace:^",
Expand Down
2 changes: 1 addition & 1 deletion examples/mean-squares-versor-registration/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
"test:wasi:long": "itk-wasm test -- -- -V",
"test:wasi:help": "itk-wasm -i itkwasm/wasi:latest run mean-squares-versor-registration.wasi.wasm -- -- --help"
},
"author": "Matt McCormick <matt@mmmccormick.com>",
"author": "Matt McCormick <matt@fideus.io>",
"license": "Apache-2.0",
"devDependencies": {
"@itk-wasm/image-io": "workspace:^",
Expand Down
20 changes: 20 additions & 0 deletions include/itkPipeline.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,13 @@
#include "itkMacro.h"
#include "itkImage.h"
#include "itkVectorImage.h"
#include "itkConfigure.h"
#if defined(ITK_USE_PTHREADS) || defined(ITK_USE_WIN32_THREADS)
#define ITK_WASM_PIPELINE_USE_THREADS 1
#endif
#ifdef ITK_WASM_PIPELINE_USE_THREADS
#include "itkMultiThreaderBase.h"
#endif

#include "glaze/glaze.hpp"

Expand Down Expand Up @@ -164,6 +171,16 @@ class WebAssemblyInterface_EXPORT Pipeline : public CLI::App
return m_UseMemoryIO;
}

int
get_threads() const
{
#ifdef ITK_WASM_PIPELINE_USE_THREADS
return m_Threads;
#else
return 1;
#endif
}

int
get_argc() const
{
Expand Down Expand Up @@ -198,6 +215,9 @@ class WebAssemblyInterface_EXPORT Pipeline : public CLI::App
int m_argc;
char ** m_argv;
std::string m_Version;
#ifdef ITK_WASM_PIPELINE_USE_THREADS
int m_Threads;
#endif
};


Expand Down
2 changes: 1 addition & 1 deletion packages/compare-images/pixi.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[project]
authors = ["Matt McCormick <matt@mmmccormick.com>"]
authors = ["Matt McCormick <matt@fideus.io>"]
channels = ["conda-forge"]
description = "Compare images with a tolerance for regression testing."
name = "compare-images"
Expand Down
2 changes: 1 addition & 1 deletion packages/compare-meshes/pixi.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[project]
authors = ["Matt McCormick <matt@mmmccormick.com>"]
authors = ["Matt McCormick <matt@fideus.io>"]
channels = ["conda-forge"]
description = "Compare meshes with a tolerance for regression testing."
name = "compare-meshes"
Expand Down
2 changes: 1 addition & 1 deletion packages/compress-stringify/pixi.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[project]
authors = ["Matt McCormick <matt@mmmccormick.com>"]
authors = ["Matt McCormick <matt@fideus.io>"]
channels = ["conda-forge"]
description = "Zstandard compression and decompression and base64 encoding and decoding in WebAssembly."
name = "compress-stringify"
Expand Down
92 changes: 46 additions & 46 deletions packages/core/typescript/itk-wasm/src/cli/find-oci-exe.js
Original file line number Diff line number Diff line change
@@ -1,46 +1,46 @@
import fs from 'fs'
import path from 'path'
import os from 'os'
import chalk from 'chalk'
import die from './die.js'
function findOciExe() {
// Check for OCI_EXE environmental variable
const ociExe = process.env.OCI_EXE
if (ociExe && fs.existsSync(ociExe)) {
return ociExe
}
// Get the PATH environment variable
const PATH = process.env.PATH.split(path.delimiter)
// Check for podman executable
const podmanExe = os.platform() === 'win32' ? 'podman.exe' : 'podman'
for (let p of PATH) {
if (fs.existsSync(path.join(p, podmanExe))) {
return podmanExe
}
}
// Check for docker executable
const dockerExe = os.platform() === 'win32' ? 'docker.exe' : 'docker'
for (let p of PATH) {
if (fs.existsSync(path.join(p, dockerExe))) {
return dockerExe
}
}
// If none of the above exist, die
die(`${chalk.magenta(`Could not find podman or docker executable in the
PATH or OCI_EXE environmental variables.`)}
${chalk.blue(`Please find installation instructions at:
https://podman.io/docs/installation`)}
`)
}
export default findOciExe
import fs from 'fs'
import path from 'path'
import os from 'os'

import chalk from 'chalk'

import die from './die.js'

function findOciExe() {
// Check for OCI_EXE environmental variable
const ociExe = process.env.OCI_EXE
if (ociExe) {
return ociExe
}

// Get the PATH environment variable
const PATH = process.env.PATH.split(path.delimiter)

// Check for podman executable
const podmanExe = os.platform() === 'win32' ? 'podman.exe' : 'podman'
for (let p of PATH) {
if (fs.existsSync(path.join(p, podmanExe))) {
return podmanExe
}
}

// Check for docker executable
const dockerExe = os.platform() === 'win32' ? 'docker.exe' : 'docker'
for (let p of PATH) {
if (fs.existsSync(path.join(p, dockerExe))) {
return dockerExe
}
}

// If none of the above exist, die
die(`${chalk.magenta(`Could not find podman or docker executable in the
PATH or OCI_EXE environmental variables.`)}

${chalk.blue(`Please find installation instructions at:

https://podman.io/docs/installation`)}

`)
}

export default findOciExe
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@ import fs from 'fs'
import EmscriptenModule from '../itk-wasm-emscripten-module.js'
import { pathToFileURL } from 'url'
import { ZSTDDecoder } from '@thewtex/zstddec'
import pthreadSupportAvailable from '../pthread-support-available.js'

const zstdDecoder = new ZSTDDecoder()
await zstdDecoder.init()

async function loadEmscriptenModuleNode (
modulePath: string
async function loadEmscriptenModuleNode(
modulePath: string,
disableThreads?: boolean
): Promise<EmscriptenModule> {
let modulePrefix = modulePath
if (modulePath.endsWith('.js')) {
Expand All @@ -19,9 +21,49 @@ async function loadEmscriptenModuleNode (
if (modulePath.endsWith('.wasm.zst')) {
modulePrefix = modulePath.substring(0, modulePath.length - 9)
}
const compressedWasmBinaryPath = `${modulePrefix}.wasm.zst`
const compressedWasmBinary = fs.readFileSync(compressedWasmBinaryPath)
const wasmBinary = zstdDecoder.decode(new Uint8Array(compressedWasmBinary))

// Check for pthread support and use the appropriate WASM file
const hasPthreadSupport = pthreadSupportAvailable() && !disableThreads
let wasmFileName = `${modulePrefix}.wasm.zst`
let wasmBinary: Uint8Array

if (hasPthreadSupport) {
const threadsWasmPath = `${modulePrefix}.threads.wasm.zst`
if (fs.existsSync(threadsWasmPath)) {
wasmFileName = threadsWasmPath
const compressedWasmBinary = fs.readFileSync(wasmFileName)
wasmBinary = zstdDecoder.decode(new Uint8Array(compressedWasmBinary))
} else {
// Fall back to checking for compressed non-threaded version
if (fs.existsSync(wasmFileName)) {
const compressedWasmBinary = fs.readFileSync(wasmFileName)
wasmBinary = zstdDecoder.decode(new Uint8Array(compressedWasmBinary))
} else {
// Fall back to uncompressed WASM file
const uncompressedWasmPath = `${modulePrefix}.wasm`
if (fs.existsSync(uncompressedWasmPath)) {
wasmBinary = fs.readFileSync(uncompressedWasmPath)
} else {
throw new Error(`No WASM file found for module: ${modulePrefix}`)
}
}
}
} else {
// Check for compressed non-threaded version first
if (fs.existsSync(wasmFileName)) {
const compressedWasmBinary = fs.readFileSync(wasmFileName)
wasmBinary = zstdDecoder.decode(new Uint8Array(compressedWasmBinary))
} else {
// Fall back to uncompressed WASM file
const uncompressedWasmPath = `${modulePrefix}.wasm`
if (fs.existsSync(uncompressedWasmPath)) {
wasmBinary = fs.readFileSync(uncompressedWasmPath)
} else {
throw new Error(`No WASM file found for module: ${modulePrefix}`)
}
}
}

const fullModulePath = pathToFileURL(`${modulePrefix}.js`).href
const result = await import(
/* webpackIgnore: true */ /* @vite-ignore */ fullModulePath
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import PipelineOutput from './pipeline-output.js'
import PipelineInput from './pipeline-input.js'
import RunPipelineResult from './run-pipeline-result.js'

function windowsToEmscriptenPath (filePath: string): string {
function windowsToEmscriptenPath(filePath: string): string {
// Following mount logic in itkJSPost.js
const fileBasename = path.basename(filePath)
const containingDir = path.dirname(filePath)
Expand All @@ -22,7 +22,7 @@ function windowsToEmscriptenPath (filePath: string): string {
return mountedPath
}

function replaceArgumentsWithEmscriptenPaths (
function replaceArgumentsWithEmscriptenPaths(
args: string[],
mountDirs: Set<string>
): string[] {
Expand All @@ -39,15 +39,26 @@ function replaceArgumentsWithEmscriptenPaths (
})
}

async function runPipelineNode (
function shouldDisableThreads(args: string[]): boolean {
for (let i = 0; i < args.length - 1; i++) {
if (args[i] === '--threads' && args[i + 1] === '0') {
return true
}
}
return false
}

async function runPipelineNode(
pipelinePath: string,
args: string[],
outputs: PipelineOutput[],
inputs: PipelineInput[] | null,
mountDirs?: Set<string>
): Promise<RunPipelineResult> {
const disableThreads = shouldDisableThreads(args)
const Module = (await loadEmscriptenModuleNode(
pipelinePath
pipelinePath,
disableThreads
)) as PipelineEmscriptenModule
const mountedDirs: Set<string> = new Set()
const unmountable: Set<string> = new Set()
Expand All @@ -61,8 +72,7 @@ async function runPipelineNode (
*/
Array.from(mountedDirs)
.filter((x, _, a) => a.every((y) => x === y || !x.includes(y)))
.forEach((dir) => unmountable.add(dir)
)
.forEach((dir) => unmountable.add(dir))
}
if (typeof mountDirs !== 'undefined') {
args = replaceArgumentsWithEmscriptenPaths(args, mountDirs)
Expand Down
Loading
Loading