or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

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

advanced-control.mddocs/

0

# Advanced Thread Pool Control

1

2

Programmatic control of thread pools with library selection, filtering, and advanced limiting patterns. The ThreadpoolController provides fine-grained control over individual libraries and their thread settings.

3

4

## Capabilities

5

6

### ThreadpoolController

7

8

Main controller class that discovers and manages all loaded thread pool libraries.

9

10

```python { .api }

11

class ThreadpoolController:

12

"""

13

Controller for all loaded supported thread pool libraries.

14

15

Automatically discovers supported libraries when instantiated and provides

16

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

17

18

Attributes:

19

lib_controllers: list[LibController]

20

List of individual library controller instances

21

"""

22

23

def __init__(self):

24

"""

25

Initialize controller and discover loaded libraries.

26

27

Scans system for loaded shared libraries and creates controllers

28

for supported thread pool libraries (BLAS and OpenMP implementations).

29

"""

30

31

def info(self):

32

"""

33

Get information about all controlled libraries.

34

35

Returns:

36

list[dict]: List of library info dicts (same format as threadpool_info())

37

"""

38

39

def select(self, **kwargs):

40

"""

41

Filter libraries by attributes.

42

43

Args:

44

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

45

is either a single value or list of acceptable values.

46

Common keys: user_api, internal_api, prefix, version, etc.

47

48

Returns:

49

ThreadpoolController: New controller with filtered library subset

50

"""

51

52

def limit(self, *, limits=None, user_api=None):

53

"""

54

Create thread limiter for this controller's libraries.

55

56

Args:

57

limits: int | dict | str | None - Thread limit specification

58

user_api: str | None - API type filter

59

60

Returns:

61

_ThreadpoolLimiter: Context manager for temporary limiting

62

"""

63

64

def wrap(self, *, limits=None, user_api=None):

65

"""

66

Create decorator for this controller's libraries.

67

68

Args:

69

limits: int | dict | str | None - Thread limit specification

70

user_api: str | None - API type filter

71

72

Returns:

73

Decorator function for thread limiting

74

"""

75

76

def __len__(self):

77

"""

78

Number of controlled libraries.

79

80

Returns:

81

int: Count of lib_controllers

82

"""

83

```

84

85

### Library Selection and Filtering

86

87

```python

88

from threadpoolctl import ThreadpoolController

89

90

# Create controller

91

controller = ThreadpoolController()

92

print(f"Found {len(controller)} thread pool libraries")

93

94

# Select by API type

95

blas_controller = controller.select(user_api='blas')

96

openmp_controller = controller.select(user_api='openmp')

97

98

# Select by implementation

99

openblas_controller = controller.select(internal_api='openblas')

100

mkl_controller = controller.select(internal_api='mkl')

101

102

# Select by multiple criteria (OR logic)

103

specific_controller = controller.select(

104

internal_api=['openblas', 'mkl'],

105

prefix='libmkl_rt'

106

)

107

108

# Select by custom attributes (for libraries that have them)

109

openmp_blas = controller.select(threading_layer='openmp')

110

```

111

112

### Advanced Limiting with Controllers

113

114

```python

115

from threadpoolctl import ThreadpoolController

116

117

controller = ThreadpoolController()

118

119

# Limit only BLAS libraries to 1 thread

120

blas_controller = controller.select(user_api='blas')

121

with blas_controller.limit(limits=1):

122

# Only BLAS libraries limited, OpenMP unchanged

123

result = numpy_computation()

124

125

# Different limits for different implementations

126

openblas_controller = controller.select(internal_api='openblas')

127

mkl_controller = controller.select(internal_api='mkl')

128

129

with openblas_controller.limit(limits=1):

130

with mkl_controller.limit(limits=2):

131

# OpenBLAS: 1 thread, MKL: 2 threads

132

result = mixed_blas_computation()

133

134

# Complex filtering and limiting

135

high_thread_controller = controller.select(

136

**{lib.prefix: lib.num_threads for lib in controller.lib_controllers

137

if lib.num_threads > 4}

138

)

139

with high_thread_controller.limit(limits=2):

140

# Only libraries with >4 threads are limited to 2

141

result = computation()

142

```

143

144

### Individual Library Controller Access

145

146

```python

147

from threadpoolctl import ThreadpoolController

148

149

controller = ThreadpoolController()

150

151

# Access individual library controllers

152

for lib_controller in controller.lib_controllers:

153

print(f"Library: {lib_controller.internal_api}")

154

print(f" Current threads: {lib_controller.num_threads}")

155

print(f" Prefix: {lib_controller.prefix}")

156

print(f" Version: {lib_controller.version}")

157

158

# Get full info dict

159

info = lib_controller.info()

160

print(f" Full info: {info}")

161

```

162

163

### FlexiBLAS Backend Management

164

165

For FlexiBLAS libraries, additional backend switching capabilities are available:

166

167

```python { .api }

168

# FlexiBLAS-specific method available on FlexiBLAS controller instances

169

def switch_backend(self, backend):

170

"""

171

Switch the FlexiBLAS backend.

172

173

Args:

174

backend: str - Backend name or path to shared library.

175

If not loaded, will be loaded first.

176

177

Raises:

178

RuntimeError: If backend loading or switching fails

179

"""

180

```

181

182

```python

183

from threadpoolctl import ThreadpoolController

184

185

controller = ThreadpoolController()

186

flexiblas_controller = controller.select(internal_api='flexiblas')

187

188

if flexiblas_controller:

189

flex_lib = flexiblas_controller.lib_controllers[0] # Get first FlexiBLAS instance

190

191

print(f"Available backends: {flex_lib.available_backends}")

192

print(f"Loaded backends: {flex_lib.loaded_backends}")

193

print(f"Current backend: {flex_lib.current_backend}")

194

195

# Switch to different backend

196

if 'OPENBLAS' in flex_lib.available_backends:

197

flex_lib.switch_backend('OPENBLAS')

198

print(f"Switched to: {flex_lib.current_backend}")

199

```

200

201

### Controller Composition Patterns

202

203

```python

204

from threadpoolctl import ThreadpoolController

205

206

# Create specialized controllers for different use cases

207

def create_compute_controller():

208

"""Controller optimized for compute workloads."""

209

controller = ThreadpoolController()

210

return controller.select(user_api='blas')

211

212

def create_parallel_controller():

213

"""Controller for parallel processing workloads."""

214

controller = ThreadpoolController()

215

return controller.select(user_api='openmp')

216

217

# Use in context

218

compute_controller = create_compute_controller()

219

parallel_controller = create_parallel_controller()

220

221

with compute_controller.limit(limits=1):

222

with parallel_controller.limit(limits=4):

223

# BLAS: 1 thread, OpenMP: 4 threads

224

result = hybrid_computation()

225

```

226

227

### Dynamic Library Management

228

229

```python

230

from threadpoolctl import ThreadpoolController

231

import importlib

232

233

# Controller state can change as new libraries are loaded

234

initial_controller = ThreadpoolController()

235

print(f"Initial libraries: {len(initial_controller)}")

236

237

# Load library that brings in new thread pools

238

import some_blas_library

239

240

# Need new controller to detect newly loaded libraries

241

updated_controller = ThreadpoolController()

242

print(f"After import: {len(updated_controller)}")

243

244

# Compare library sets

245

initial_libs = {lib.filepath for lib in initial_controller.lib_controllers}

246

updated_libs = {lib.filepath for lib in updated_controller.lib_controllers}

247

new_libs = updated_libs - initial_libs

248

print(f"New libraries: {list(new_libs)}")

249

```

250

251

### Error Handling and Edge Cases

252

253

```python

254

from threadpoolctl import ThreadpoolController

255

256

controller = ThreadpoolController()

257

258

# Handle empty selections

259

blis_controller = controller.select(internal_api='blis')

260

if len(blis_controller) == 0:

261

print("No BLIS libraries found")

262

else:

263

with blis_controller.limit(limits=1):

264

result = computation()

265

266

# Robust library access

267

openblas_controllers = controller.select(internal_api='openblas')

268

if openblas_controllers:

269

for lib in openblas_controllers.lib_controllers:

270

try:

271

# Some old OpenBLAS versions may not support all operations

272

threads = lib.num_threads

273

lib.set_num_threads(1)

274

lib.set_num_threads(threads) # Restore

275

except Exception as e:

276

print(f"Library {lib.prefix} error: {e}")

277

```