mirror of
https://github.com/python-pillow/Pillow.git
synced 2025-02-06 22:50:55 +03:00
Set default max threads in Python (#4)
* Removed unused C values * Set default max threads in Python --------- Co-authored-by: Andrew Murray <radarhere@users.noreply.github.com>
This commit is contained in:
parent
d6a0a15f53
commit
50b993a0cb
|
@ -1,5 +1,6 @@
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import os
|
||||||
from io import BytesIO
|
from io import BytesIO
|
||||||
from typing import IO
|
from typing import IO
|
||||||
|
|
||||||
|
@ -46,6 +47,15 @@ def _accept(prefix: bytes) -> bool | str:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def _get_default_max_threads():
|
||||||
|
if DEFAULT_MAX_THREADS:
|
||||||
|
return DEFAULT_MAX_THREADS
|
||||||
|
if hasattr(os, "sched_getaffinity"):
|
||||||
|
return len(os.sched_getaffinity(0))
|
||||||
|
else:
|
||||||
|
return os.cpu_count() or 1
|
||||||
|
|
||||||
|
|
||||||
class AvifImageFile(ImageFile.ImageFile):
|
class AvifImageFile(ImageFile.ImageFile):
|
||||||
format = "AVIF"
|
format = "AVIF"
|
||||||
format_description = "AVIF image"
|
format_description = "AVIF image"
|
||||||
|
@ -64,7 +74,10 @@ class AvifImageFile(ImageFile.ImageFile):
|
||||||
raise SyntaxError(msg)
|
raise SyntaxError(msg)
|
||||||
|
|
||||||
self._decoder = _avif.AvifDecoder(
|
self._decoder = _avif.AvifDecoder(
|
||||||
self.fp.read(), DECODE_CODEC_CHOICE, CHROMA_UPSAMPLING, DEFAULT_MAX_THREADS
|
self.fp.read(),
|
||||||
|
DECODE_CODEC_CHOICE,
|
||||||
|
CHROMA_UPSAMPLING,
|
||||||
|
_get_default_max_threads(),
|
||||||
)
|
)
|
||||||
|
|
||||||
# Get info from decoder
|
# Get info from decoder
|
||||||
|
@ -140,7 +153,7 @@ def _save(
|
||||||
duration = info.get("duration", 0)
|
duration = info.get("duration", 0)
|
||||||
subsampling = info.get("subsampling", "4:2:0")
|
subsampling = info.get("subsampling", "4:2:0")
|
||||||
speed = info.get("speed", 6)
|
speed = info.get("speed", 6)
|
||||||
max_threads = info.get("max_threads", DEFAULT_MAX_THREADS)
|
max_threads = info.get("max_threads", _get_default_max_threads())
|
||||||
codec = info.get("codec", "auto")
|
codec = info.get("codec", "auto")
|
||||||
range_ = info.get("range", "full")
|
range_ = info.get("range", "full")
|
||||||
tile_rows_log2 = info.get("tile_rows", 0)
|
tile_rows_log2 = info.get("tile_rows", 0)
|
||||||
|
|
89
src/_avif.c
89
src/_avif.c
|
@ -44,54 +44,6 @@ typedef struct {
|
||||||
|
|
||||||
static PyTypeObject AvifDecoder_Type;
|
static PyTypeObject AvifDecoder_Type;
|
||||||
|
|
||||||
static int default_max_threads = 0;
|
|
||||||
|
|
||||||
static void
|
|
||||||
init_max_threads(void) {
|
|
||||||
PyObject *os = NULL;
|
|
||||||
PyObject *n = NULL;
|
|
||||||
long num_cpus;
|
|
||||||
|
|
||||||
os = PyImport_ImportModule("os");
|
|
||||||
if (os == NULL) {
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (PyObject_HasAttrString(os, "sched_getaffinity")) {
|
|
||||||
n = PyObject_CallMethod(os, "sched_getaffinity", "i", 0);
|
|
||||||
if (n == NULL) {
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
num_cpus = PySet_Size(n);
|
|
||||||
} else {
|
|
||||||
n = PyObject_CallMethod(os, "cpu_count", NULL);
|
|
||||||
if (n == NULL) {
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
num_cpus = PyLong_AsLong(n);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (num_cpus < 1) {
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
default_max_threads = (int)num_cpus;
|
|
||||||
|
|
||||||
done:
|
|
||||||
Py_XDECREF(os);
|
|
||||||
Py_XDECREF(n);
|
|
||||||
return;
|
|
||||||
|
|
||||||
error:
|
|
||||||
if (PyErr_Occurred()) {
|
|
||||||
PyErr_Clear();
|
|
||||||
}
|
|
||||||
PyErr_WarnEx(
|
|
||||||
PyExc_RuntimeWarning, "could not get cpu count: using max_threads=1", 1
|
|
||||||
);
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
normalize_quantize_value(int qvalue) {
|
normalize_quantize_value(int qvalue) {
|
||||||
if (qvalue < AVIF_QUANTIZER_BEST_QUALITY) {
|
if (qvalue < AVIF_QUANTIZER_BEST_QUALITY) {
|
||||||
|
@ -306,23 +258,23 @@ AvifEncoderNew(PyObject *self_, PyObject *args) {
|
||||||
AvifEncoderObject *self = NULL;
|
AvifEncoderObject *self = NULL;
|
||||||
avifEncoder *encoder = NULL;
|
avifEncoder *encoder = NULL;
|
||||||
|
|
||||||
char *subsampling = "4:2:0";
|
char *subsampling;
|
||||||
int qmin = AVIF_QUANTIZER_BEST_QUALITY; // =0
|
int qmin;
|
||||||
int qmax = 10; // "High Quality", but not lossless
|
int qmax;
|
||||||
int quality = 75;
|
int quality;
|
||||||
int speed = 8;
|
int speed;
|
||||||
int exif_orientation = 0;
|
int exif_orientation;
|
||||||
int max_threads = default_max_threads;
|
int max_threads;
|
||||||
PyObject *icc_bytes;
|
PyObject *icc_bytes;
|
||||||
PyObject *exif_bytes;
|
PyObject *exif_bytes;
|
||||||
PyObject *xmp_bytes;
|
PyObject *xmp_bytes;
|
||||||
PyObject *alpha_premultiplied = NULL;
|
PyObject *alpha_premultiplied;
|
||||||
PyObject *autotiling = NULL;
|
PyObject *autotiling;
|
||||||
int tile_rows_log2 = 0;
|
int tile_rows_log2;
|
||||||
int tile_cols_log2 = 0;
|
int tile_cols_log2;
|
||||||
|
|
||||||
char *codec = "auto";
|
char *codec;
|
||||||
char *range = "full";
|
char *range;
|
||||||
|
|
||||||
PyObject *advanced;
|
PyObject *advanced;
|
||||||
|
|
||||||
|
@ -438,13 +390,6 @@ AvifEncoderNew(PyObject *self_, PyObject *args) {
|
||||||
|
|
||||||
encoder = avifEncoderCreate();
|
encoder = avifEncoderCreate();
|
||||||
|
|
||||||
if (max_threads == 0) {
|
|
||||||
if (default_max_threads == 0) {
|
|
||||||
init_max_threads();
|
|
||||||
}
|
|
||||||
max_threads = default_max_threads;
|
|
||||||
}
|
|
||||||
|
|
||||||
int is_aom_encode = strcmp(codec, "aom") == 0 ||
|
int is_aom_encode = strcmp(codec, "aom") == 0 ||
|
||||||
(strcmp(codec, "auto") == 0 &&
|
(strcmp(codec, "auto") == 0 &&
|
||||||
_codec_available("aom", AVIF_CODEC_FLAG_CAN_ENCODE));
|
_codec_available("aom", AVIF_CODEC_FLAG_CAN_ENCODE));
|
||||||
|
@ -730,7 +675,7 @@ AvifDecoderNew(PyObject *self_, PyObject *args) {
|
||||||
char *codec_str;
|
char *codec_str;
|
||||||
avifCodecChoice codec;
|
avifCodecChoice codec;
|
||||||
avifChromaUpsampling upsampling;
|
avifChromaUpsampling upsampling;
|
||||||
int max_threads = 0;
|
int max_threads;
|
||||||
|
|
||||||
avifResult result;
|
avifResult result;
|
||||||
|
|
||||||
|
@ -785,12 +730,6 @@ AvifDecoderNew(PyObject *self_, PyObject *args) {
|
||||||
|
|
||||||
self->decoder = avifDecoderCreate();
|
self->decoder = avifDecoderCreate();
|
||||||
#if AVIF_VERSION >= 80400
|
#if AVIF_VERSION >= 80400
|
||||||
if (max_threads == 0) {
|
|
||||||
if (default_max_threads == 0) {
|
|
||||||
init_max_threads();
|
|
||||||
}
|
|
||||||
max_threads = default_max_threads;
|
|
||||||
}
|
|
||||||
self->decoder->maxThreads = max_threads;
|
self->decoder->maxThreads = max_threads;
|
||||||
#endif
|
#endif
|
||||||
#if AVIF_VERSION >= 90200
|
#if AVIF_VERSION >= 90200
|
||||||
|
|
Loading…
Reference in New Issue
Block a user