or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

advanced-control.mdcustom-libraries.mdindex.mdintrospection.mdlimiting.md

index.mddocs/

0

# Threadpoolctl

1

2

Python helpers to limit the number of threads used in threadpool-backed native libraries for scientific computing and data science (e.g. BLAS and OpenMP). Fine control of underlying thread-pool sizes helps mitigate oversubscription issues in workloads involving nested parallelism.

3

4

## Package Information

5

6

- **Package Name**: threadpoolctl

7

- **Language**: Python

8

- **Installation**: `pip install threadpoolctl`

9

10

## Core Imports

11

12

```python

13

from threadpoolctl import threadpool_info, threadpool_limits, ThreadpoolController

14

```

15

16

For library controller registration:

17

18

```python

19

from threadpoolctl import LibController, register

20

```

21

22

## Basic Usage

23

24

```python

25

from threadpoolctl import threadpool_info, threadpool_limits

26

27

# Inspect current thread pool state

28

info = threadpool_info()

29

print(f"Found {len(info)} libraries with thread pools")

30

31

# Limit threads temporarily with context manager

32

with threadpool_limits(limits=1):

33

# All thread pools limited to 1 thread

34

# Your computation here

35

pass

36

37

# Limit specific API types

38

with threadpool_limits(limits=2, user_api='blas'):

39

# Only BLAS libraries limited to 2 threads

40

# Your computation here

41

pass

42

43

# Use as decorator

44

@threadpool_limits(limits=1)

45

def compute():

46

# Function runs with thread pools limited to 1 thread

47

pass

48

```

49

50

## Architecture

51

52

Threadpoolctl's architecture centers around **Library Controllers** that manage specific thread pool implementations:

53

54

- **ThreadpoolController**: Main controller that discovers and manages all loaded thread pool libraries

55

- **LibController**: Abstract base class for individual library controllers

56

- **Concrete Controllers**: Specific implementations for OpenBLAS, MKL, BLIS, FlexiBLAS, and OpenMP

57

- **Thread Limiters**: Context managers and decorators for temporarily changing thread limits

58

59

The library automatically detects loaded scientific computing libraries and provides a unified interface for thread pool control across different implementations.

60

61

## Capabilities

62

63

### Thread Pool Introspection

64

65

Discover and inspect thread pool libraries currently loaded in the Python process, returning detailed information about each library including version, thread count, and implementation details.

66

67

```python { .api }

68

def threadpool_info() -> list[dict[str, Any]]:

69

"""

70

Return thread pool information for all detected libraries.

71

72

Scans loaded shared libraries and returns information for supported

73

thread pool libraries (BLAS implementations and OpenMP runtimes).

74

75

Returns:

76

list[dict[str, Any]]: List of library info dictionaries with keys:

77

- user_api: str ('blas', 'openmp')

78

- internal_api: str ('openblas', 'mkl', 'blis', 'flexiblas', 'openmp')

79

- prefix: str (library filename prefix)

80

- filepath: str (path to loaded shared library)

81

- version: str | None (library version if available)

82

- num_threads: int (current thread limit)

83

- Additional implementation-specific attributes

84

"""

85

```

86

87

[Thread Pool Introspection](./introspection.md)

88

89

### Thread Limiting

90

91

Temporarily limit the number of threads used by thread pool libraries using context managers or decorators, with support for global limits, per-API limits, or per-library limits.

92

93

```python { .api }

94

class threadpool_limits:

95

"""

96

Context manager/decorator for limiting thread pool sizes.

97

98

Can be used as callable, context manager, or decorator.

99

100

Args:

101

limits: int | dict[str, int] | str | None

102

- int: Global thread limit for all libraries

103

- dict: Per-API or per-library limits {api/prefix: limit}

104

- 'sequential_blas_under_openmp': Special case for nested parallelism

105

- None: No limits applied

106

user_api: str | None ('blas', 'openmp', None)

107

API type to limit when limits is int

108

"""

109

110

def __init__(self, limits=None, user_api=None): ...

111

112

def __enter__(self) -> 'threadpool_limits':

113

"""Enter context manager, returns self."""

114

115

def __exit__(self, type, value, traceback) -> None:

116

"""Exit context manager, restores original limits."""

117

118

def restore_original_limits(self) -> None:

119

"""Manually restore original thread limits."""

120

121

def unregister(self) -> None:

122

"""Alias for restore_original_limits() (backward compatibility)."""

123

124

def get_original_num_threads(self) -> dict[str, int]:

125

"""

126

Get original thread counts before limiting.

127

128

Returns:

129

dict[str, int]: Original thread counts by user_api

130

"""

131

132

@classmethod

133

def wrap(cls, limits=None, user_api=None) -> 'Callable':

134

"""

135

Create decorator version that delays limit setting.

136

137

Returns:

138

Callable: Decorator function for use with @threadpool_limits.wrap(...)

139

"""

140

```

141

142

[Thread Limiting](./limiting.md)

143

144

### Advanced Thread Pool Control

145

146

Programmatic control of thread pools with library selection, filtering, and advanced limiting patterns for complex scientific computing workloads.

147

148

```python { .api }

149

class ThreadpoolController:

150

"""

151

Controller for all loaded supported thread pool libraries.

152

153

Automatically discovers supported libraries when instantiated and provides

154

methods for filtering, selecting, and controlling their thread settings.

155

156

Attributes:

157

lib_controllers: list[LibController] - Individual library controllers

158

"""

159

160

def __init__(self):

161

"""Initialize controller and discover loaded libraries."""

162

163

def info(self) -> list[dict[str, Any]]:

164

"""

165

Get information about all controlled libraries.

166

167

Returns:

168

list[dict[str, Any]]: List of library info dicts

169

"""

170

171

def select(self, **kwargs) -> 'ThreadpoolController':

172

"""

173

Filter libraries by attributes.

174

175

Args:

176

**kwargs: Attribute filters where key is attribute name and value

177

is either a single value or list of acceptable values.

178

179

Returns:

180

ThreadpoolController: New controller with filtered library subset

181

"""

182

183

def limit(self, *, limits=None, user_api=None) -> '_ThreadpoolLimiter':

184

"""

185

Create thread limiter for this controller's libraries.

186

187

Args:

188

limits: int | dict[str, int] | str | None - Thread limit specification

189

user_api: str | None - API type filter

190

191

Returns:

192

_ThreadpoolLimiter: Context manager for temporary limiting

193

"""

194

195

def wrap(self, *, limits=None, user_api=None) -> 'Callable':

196

"""

197

Create decorator for this controller's libraries.

198

199

Args:

200

limits: int | dict[str, int] | str | None - Thread limit specification

201

user_api: str | None - API type filter

202

203

Returns:

204

Callable: Decorator function for thread limiting

205

"""

206

207

def __len__(self) -> int:

208

"""

209

Number of controlled libraries.

210

211

Returns:

212

int: Count of lib_controllers

213

"""

214

```

215

216

[Advanced Control](./advanced-control.md)

217

218

### Custom Library Support

219

220

Extend threadpoolctl with custom library controllers for additional thread pool libraries not supported out of the box.

221

222

```python { .api }

223

class LibController:

224

"""

225

Abstract base class for individual library controllers.

226

227

Class Attributes:

228

user_api: str - Standardized API name ('blas', 'openmp', etc.)

229

internal_api: str - Implementation-specific identifier

230

filename_prefixes: tuple[str, ...] - Library filename prefixes to match

231

check_symbols: tuple[str, ...] - Optional symbol names to verify compatibility

232

"""

233

234

def __init__(self, *, filepath=None, prefix=None, parent=None):

235

"""

236

Initialize library controller.

237

238

Args:

239

filepath: str | None - Path to shared library file

240

prefix: str | None - Matched filename prefix

241

parent: ThreadpoolController | None - Parent controller instance

242

"""

243

244

def info(self) -> dict[str, Any]:

245

"""

246

Return library information dictionary.

247

248

Returns:

249

dict: Library info with standard keys plus additional attributes

250

"""

251

252

def get_num_threads(self) -> int | None:

253

"""

254

Get current maximum thread count (abstract method).

255

256

Returns:

257

int | None: Current thread limit, None if unavailable

258

"""

259

260

def set_num_threads(self, num_threads: int) -> Any:

261

"""

262

Set maximum thread count (abstract method).

263

264

Args:

265

num_threads: int - New thread limit

266

267

Returns:

268

Any: Implementation-specific return value

269

"""

270

271

def get_version(self) -> str | None:

272

"""

273

Get library version (abstract method).

274

275

Returns:

276

str | None: Version string, None if unavailable

277

"""

278

279

def set_additional_attributes(self) -> None:

280

"""

281

Set implementation-specific attributes.

282

283

Called during initialization to set custom attributes that will

284

be included in the info() dictionary.

285

"""

286

287

@property

288

def num_threads(self) -> int | None:

289

"""Current thread limit (dynamic property)."""

290

291

def register(controller: type[LibController]) -> None:

292

"""

293

Register a new library controller class.

294

295

Adds the controller to the global registry so it will be used

296

during library discovery in future ThreadpoolController instances.

297

298

Args:

299

controller: type[LibController] - LibController subclass to register

300

"""

301

```

302

303

[Custom Library Support](./custom-libraries.md)

304

305

## Command Line Interface

306

307

Threadpoolctl provides a command-line interface to inspect thread pool libraries loaded by Python packages.

308

309

```bash { .api }

310

# Basic usage

311

python -m threadpoolctl

312

313

# Import specific modules before introspection

314

python -m threadpoolctl -i numpy scipy.linalg xgboost

315

316

# Execute Python code before introspection

317

python -m threadpoolctl -c "import sklearn; from sklearn.ensemble import RandomForestClassifier"

318

319

# Combined usage

320

python -m threadpoolctl -i numpy -c "import threading; print(f'Python threads: {threading.active_count()}')"

321

```

322

323

**Arguments:**

324

- `-i, --import MODULE [MODULE ...]`: Import Python modules before introspecting thread pools

325

- `-c, --command COMMAND`: Execute Python statement before introspecting thread pools

326

327

**Output:** JSON-formatted list of thread pool library information written to stdout. Warning messages for missing modules are written to stderr.

328

329

**Example Output:**

330

```json

331

[

332

{

333

"filepath": "/usr/lib/libmkl_rt.so",

334

"prefix": "libmkl_rt",

335

"user_api": "blas",

336

"internal_api": "mkl",

337

"version": "2019.0.4",

338

"num_threads": 2,

339

"threading_layer": "intel"

340

}

341

]

342

```

343

344

## Types

345

346

```python { .api }

347

# Library information dictionary structure

348

LibraryInfo = dict[str, Any] # Keys: user_api, internal_api, prefix, filepath, version, num_threads, ...

349

350

# Thread limit specifications

351

ThreadLimits = int | dict[str, int] | str | None

352

353

# API type specifications

354

UserAPI = Literal["blas", "openmp"] | None

355

```