Exercice 2 d'exemple d'optimisation des performances Python - optimisation détaillée (ctypes, etc., inachevé)

Ce chapitre continue à utiliser le système de connaissances "Python Performance Analysis and Optimization" écrit par Fernando Doglio, principalement basé sur les détails de l'optimisation et combiné avec sa propre application pratique. L'accent est mis sur l'utilisation des ctypes.

Cache de valeur de retour de fonction/table de recherche de fonction

Utilisation des paramètres par défaut

Le paramètre par défaut (argument par défaut) peut déterminer la valeur d'entrée lors de la création de la fonction , au lieu de déterminer l'entrée au moment de l'exécution.

Passez en revue les paramètres python ici :

  1. arguments positionnels

  2. argument de mot-clé

    def trapezoid_area(base_up, base_down, height)
    	return 1/2 * (base_up + base_down) * height
    
    trapezoid_area(1, 2, 3) # 位置参数
    trapezoid_area(base_up=1, base_down=2, height=3) # 关键词参数
    trapezoid_area(height=3, base_down=2, base_up=1) # right
    trapezoid_area(height=1, base_down=2, 1) # wrong
    trapezoid_area(base_up=1, base_down=2, 3) # right
    trapezoid_area(1, 2, height=3)
    
  3. paramètres par défaut

    Paramètre par défaut = valeur par défaut, lors de l'appel de la fonction, si la valeur du paramètre par défaut n'est pas passée, elle sera considérée comme la valeur par défaut.

    Le paramètre par défaut doit être placé après , sinon le programme signalera une erreur.

    def trapezoid_area(base_up, base_down, height=3)
    	return 1/2 * (base_up + base_down) * height
    trapezoid_area(1, 2) 
    trapezoid_area(1, 2, height=3) # 位置参数
    
  4. argument variable

    Un paramètre variable signifie que le nombre de paramètres transmis est variable, qui peut être de 0, 1, 2 à n'importe quel nombre, et est un paramètre de longueur variable.

    def printinfo(arg1, *args): # *args - 可变参数,可以是从零个到任意个,自动组装成元组。
        print('arg1:' + str(arg1))
        print('args:', end=' ')
        for var in args:
            print(var, end=' ')
        print(' ')
    
    
    printinfo(10)  # 10
    printinfo(70, 60, 50)
    

    Le résultat de l'exécution du programme est :

    arg1:10
    args:  
    arg1:70
    args: 60 50  
    
    Process finished with exit code 0
    
  5. Arguments de mots clés

    def printinfo(arg1, *args, **kwargs): # **kwargs - 关键字参数,可以是从零个到任意个,自动组装成字典。
        print(arg1)
        print(args)
        print(kwargs)
    
    
    printinfo(70, 60, 50)
    # 70
    # (60, 50)
    # {}
    printinfo(70, 60, 50, a=1, b=2)
    # 70
    # (60, 50)
    # {'a': 1, 'b': 2}
    

    La partie commentaire dans le programme est le résultat courant.

  6. Arguments de mots-clés nommés (argument de mot-clé de nom)

    • *, nkw- Paramètres de mots clés nommés, les paramètres de mots clés que l'utilisateur souhaite saisir, définis en ajoutant un séparateur devant nkw *.
    • Si vous souhaitez restreindre les noms des paramètres de mots clés, vous pouvez utiliser des "paramètres de mots clés nommés"
    • Lorsque vous utilisez des paramètres de mots-clés nommés, faites particulièrement attention à ce que le nom du paramètre ne puisse pas manquer
    def printinfo(arg1, *, nkw, **kwargs):
        print(arg1)
        print(nkw)
        print(kwargs)
    
    
    printinfo(70, nkw=10, a=1, b=2)
    # 70
    # 10
    # {'a': 1, 'b': 2}
    
    printinfo(70, 10, a=1, b=2)
    # TypeError: printinfo() takes 1 positional argument but 2 were given
    
  7. combinaison de paramètres

    Pour définir une fonction en Python, vous pouvez utiliser des paramètres positionnels, des paramètres par défaut, des paramètres variables, des paramètres de mots-clés nommés et des paramètres de mots-clés. Quatre de ces cinq types de paramètres peuvent être utilisés ensemble, mais notez que l'ordre de définition des paramètres doit être :

    • Arguments positionnels, arguments par défaut, arguments variadiques et arguments de mots-clés.
    • Arguments positionnels, arguments par défaut, arguments de mots clés nommés et arguments de mots clés.

    Notez la syntaxe de définition des arguments variadiques et des mots-clés :

    • *argsC'est un paramètre variable, et argsil reçoit untuple
    • **kwargsest un argument mot-clé qui kwreçoit undict

    Les paramètres de mots clés nommés sont utilisés pour limiter les noms de paramètres que l'appelant peut transmettre, tout en fournissant des valeurs par défaut. N'oubliez pas d'écrire le délimiteur lors de la définition du paramètre de mot-clé nommé *, sinon la définition est un paramètre de position.

    Avertissement : bien que vous puissiez combiner jusqu'à 5 arguments, n'utilisez pas trop de combinaisons en même temps, sinon la fonction deviendra confuse.

Générateur d'expressions de synthèse de liste

Placez les opérations telles que l'initialisation devant les calculs du programme et remplacez les boucles for par des expressions de synthèse de liste.

final_state_list = [FinalStatus() for x in range(opt.multiple_camera_number)]

ctypes

La bibliothèque ctypes permet aux développeurs d'accéder directement à la couche inférieure de Python et de développer avec la puissance du langage C. Cette bibliothèque n'est disponible que dans la version officielle de l'interpréteur (CPython), car cette version est écrite en langage C. Les autres versions, telles que PyPy et Jython, ne peuvent pas accéder à cette bibliothèque.

À ce stade, nous pouvons écrire le code clé en langage C, le compiler dans une bibliothèque, puis l'importer dans Python en tant que module.

Comment juger quel interpréteur python est J'ai modifié le code dans le texte original, il suffit de cv et de l'exécuter dans votre propre environnement python pour savoir quel interpréteur est utilisé.

import sys
import os
try:
    from platform import python_implementation
except ImportError: # pragma: no cover
    def python_implementation():
        """Return a string identifying the Python implementation."""
        if 'PyPy' in sys.version:
            print('PyPy')
        if os.name == 'java':
            print('Jython')
        if sys.version.startswith('IronPython'):
            print('IronPython')
finally:
    print('CPython')

Utilisation de ctypes

En ce qui concerne l'utilisation de ctypes, j'ai lu quelques articles et j'ai trouvé que c'était un peu compliqué. Personnellement, je pense que l'utilisation de ctypes consiste à peu près à compiler le code c pur dans une bibliothèque de liens externes et à importer cette bibliothèque de liens externes dans python à utiliser.

La première étape : créez d'abord ctypes_test.c

// 这是找素数的程序
#include <stdio.h>
#include <math.h>
int check_prime(int a)
{
    
    
    int c;
    for ( c = 2 ; c <= sqrt(a) ; c++ ) {
    
    
        if ( a%c == 0 )
        return 0;
    }
    return 1;
}

Etape 2 : Compiler le fichier

$ gcc -shared -o ct.so -fPIC .\ctypes_test.c

Mon environnement est en anaconda, et gcc a été installé gcc version 8.1.0 (x86_64-posix-sjlj-rev0, Built by MinGW-W64 project), quelques compléments concernant les paramètres de gcc :

paramètre Fonction
-partagé Cette option interdira l'utilisation de bibliothèques dynamiques, de sorte que les éléments compilés sont généralement très volumineux et qu'ils peuvent s'exécuter sans aucune bibliothèque de liens dynamiques.
-statique Cette option essaiera d'utiliser la bibliothèque dynamique, donc le fichier généré est relativement petit, mais le système a besoin de la bibliothèque dynamique.
-fPIC C'est une bibliothèque de liens dynamiques ?

Étape 3 : Appelez la bibliothèque générée dans le programme python

import time
import ctypes
import math
# ctypes.CDLL(name, mode=DEFAULT_MODE, handle=None, use_errno=False, use_last_error=False)
check_primes_types = ctypes.CDLL('./ct.so').check_prime  # ctypes.CDLL('路径').函数名

def check_prime(x):
    values = range(2, int(math.sqrt(x)))
    for i in values:
        if x % i == 0:
            return False
    return True


init = time.time()
numbers_py = [x for x in range(1000000) if check_prime(x)]
print("Full python version: %s seconds" % (time.time() - init))
init = time.time()
numbers_c = [x for x in range(1000000) if check_primes_types(x)]
print("C version: %s seconds" % (time.time() - init))
print(len(numbers_py))

Précautions

Valeur de retour : à propos du type de paramètre et du type de valeur de retour lorsque ctypes appelle dll

Paramètres : python appelle le code c/c++ et résout ctypes.ArgumentError : argument 1 : classe 'TypeError' : Je ne sais pas comment convertir

Le paramètre est un tableau : l'utilisation de ctypes (en passant un tableau numpy dans c)

concaténation de chaînes

Étant donné que les chaînes sont immuables, chaque fois que nous faisons quoi que ce soit pour modifier le contenu d'une chaîne, nous créons en fait une nouvelle chaîne avec un nouveau contenu, et notre variable pointera vers la chaîne nouvellement créée.

Fusionner des chaînes dans une liste

full_doc = ""
for word in word_list:
	full_doc += word

réécrit comme

full_doc = "".join(world_list)

interpolation variable

document = "%s%s%s%s" % (title, introduction, main_piece, conclusion)

Autres conseils d'optimisation Python

supprimer les programmes inutiles

# 173行
imc = im0.copy() if opt.save_crop else im0  # for save_crop

Guess you like

Origin blog.csdn.net/weixin_42442319/article/details/127751793