mirror of
				https://github.com/python-pillow/Pillow.git
				synced 2025-11-04 01:47:47 +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