Maison > développement back-end > C++ > Comment puis-je optimiser ma transformation théorique des nombres (NTT) et mon arithmétique modulaire pour un calcul plus rapide, en particulier avec de très grands nombres (par exemple, plus de 12 000 bits) ?

Comment puis-je optimiser ma transformation théorique des nombres (NTT) et mon arithmétique modulaire pour un calcul plus rapide, en particulier avec de très grands nombres (par exemple, plus de 12 000 bits) ?

Barbara Streisand
Libérer: 2024-12-16 03:13:18
original
545 Les gens l'ont consulté

How can I optimize my Number Theoretic Transform (NTT) and modular arithmetic for faster computation, especially with very large numbers (e.g., over 12000 bits)?

Arithmétique modulaire et optimisations NTT (DFT à champs finis)

Énoncé du problème


Je voulais utiliser NTT pour obtenir rapidement quadrature (voir Calcul rapide du carré bignum), mais le résultat est lent même pour de très grands nombres .. plus de 12000 bits.


Ma question est donc :

< ;ol>

  • Y a-t-il un moyen d'optimiser ma transformation NTT ? Je ne voulais pas l'accélérer par parallélisme (threads) ; il s'agit uniquement d'une couche de bas niveau.

  • Existe-t-il un moyen d'accélérer mon calcul modulaire ?


  • Voici mon code source (déjà optimisé) en C pour NTT (il est complet et fonctionne à 100% en C sans avoir besoin de bibliothèques tierces et doit également être thread-safe. Attention, le tableau source est utilisé comme temporaire !!!, il ne peut pas non plus transformer le tableau en lui-même).
    < /p>

    Solution optimisée

    1. Utilisation de puissances précalculées : Précalcul et stocker les puissances de W et iW (la racine primitive de l'unité et son inverse) pour éviter de les recalculer pendant le processus NTT. Cela peut réduire considérablement le nombre de multiplications et de divisions, conduisant à des calculs plus rapides.
    2. Déroulage des boucles : Déroulez les boucles dans l'algorithme NTT pour réduire la surcharge associée aux itérations de boucle. Cela peut améliorer les performances en réduisant le nombre d'instructions de branchement.
    3. Optimisation de l'arithmétique modulaire : Utilisez les opérations au niveau des bits et le langage d'assemblage pour implémenter efficacement les opérations arithmétiques modulaires (addition, soustraction, multiplication et exponentiation). . Cela peut éliminer les branchements inutiles et les instructions conditionnelles, ce qui entraîne une exécution plus rapide.

    Exemple d'implémentation

    Voici un exemple d'implémentation NTT optimisée en C utilisant des puissances précalculées et des opérations au niveau du bit :

    class NTT {
    public:
        NTT() {
            // Initialize constants
            p = 0xc0000001;
            W = modpow(2, 0x30000000 / n);
            iW = modpow(2, p - 1 - 0x30000000 / n);
            rN = modpow(n, p - 2);
            NN = n >> 1;
    
            // Precompute W and iW powers
            WW = new uint32_t[n];
            iWW = new uint32_t[n];
            WW[0] = 1;
            iWW[0] = 1;
            for (uint32_t i = 1; i < n; i++) {
                WW[i] = modmul(WW[i - 1], W);
                iWW[i] = modmul(iWW[i - 1], iW);
            }
        }
    
        void NTT(uint32_t *dst, uint32_t *src, uint32_t n) {
            if (n > 0) {
                // Reorder even, odd elements
                for (uint32_t i = 0, j = 0; i < NN; i++, j += 2) {
                    dst[i] = src[j];
                }
                for (j = 1; i < n; i++, j += 2) {
                    dst[i] = src[j];
                }
    
                // Recursive NTT
                NTT(src, dst, NN);  // Even
                NTT(src + NN, dst + NN, NN);  // Odd
    
                // Restore results
                for (uint32_t i = 0, j = NN; i < NN; i++, j++) {
                    uint32_t a0 = src[i];
                    uint32_t a1 = modmul(src[j], WW[i]);
                    dst[i] = modadd(a0, a1);
                    dst[j] = modsub(a0, a1);
                }
            }
        }
    
    private:
        uint32_t p, n, NN, W, iW, rN;
        uint32_t *WW, *iWW;
    
        // Modular arithmetic operations
        inline uint32_t modadd(uint32_t a, uint32_t b) {
            uint32_t d = a + b;
            if (d >= p) d -= p;
            return d;
        }
    
        inline uint32_t modsub(uint32_t a, uint32_t b) {
            uint32_t d = a - b;
            if (d > a) d += p;
            return d;
        }
    
        inline uint32_t modmul(uint32_t a, uint32_t b) {
            uint32_t m = (uint64_t)a * b;
            return m - (p * (m / p));
        }
    
        inline uint32_t modpow(uint32_t a, uint32_t b) {
            if (b == 0) return 1;
            uint32_t t = modpow(a, b / 2);
            t = modmul(t, t);
            if (b &amp; 1) t = modmul(t, a);
            return t;
        }
    };
    Copier après la connexion

    Conseils supplémentaires

    • Utilisez un langage de niveau supérieur prenant en charge opérations au niveau du bit et assemblage en ligne, tels que C .
    • Utilisez un profileur pour identifier les goulots d'étranglement dans votre code et ciblez-les pour l'optimisation.
    • Envisagez de paralléliser l'algorithme NTT à l'aide de plusieurs threads ou d'instructions SIMD.

    Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

    source:php.cn
    Déclaration de ce site Web
    Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
    Derniers articles par auteur
    Tutoriels populaires
    Plus>
    Derniers téléchargements
    Plus>
    effets Web
    Code source du site Web
    Matériel du site Web
    Modèle frontal