Autor Tema: Propuesta de test de primalidad para números de Mersenne

jhonny guanipa y 1 Visitante están viendo este tema.

16 Junio, 2026, 11:51 am
Respuesta #20

jhonny guanipa

  • $$\Large \color{#6a84c0}\pi$$
  • Mensajes: 13
  • País: ve
  • Karma: +0/-0
HOLA luis,

Gracias por dar tus observaciones, te comparto una salida de prueba del algoritmo con las 8 clases.
lo que quise decir con \( 24k+7 \) (que es una de las 8 clases) es que me da los doble Mersenne y otros Mersenne, el \( M_5 \) está en la clase 5.

Lo que dices del colapso de la memoria es totalmente cierto y hasta ahora en el punto débil, de allí mi solicitud de apoyo a la comunidad a ver de que modo se pudiera corregir eso, quizas trabajando en segmentos, \( s=10^7 \) ??? s=\( 5\cdot 10^6 \)?? no lo se, en todo caso seria interesante revisar a nivel de implementaciones.
Por último el tema de los bucles lo estoy revisando asiícomo otras cosas, parece tema resuelto prontamente. Lo que si me preocupa es el tema del colapso de la memoria, sin corregir eso, veo inviable esta ruta, al menos para rangos grandes que es lo que necesitamos.

Saludos cordiales y seguimos trabajando.



============================================================
Clase  1:  187948 primos
         Exponentes de Mersenne: [2281, 3217, 23209, 44497, 132049]
Clase  5:  188352 primos
         Exponentes de Mersenne: [5, 4253, 9941, 11213, 21701, 1398269, 2976221]
Clase  7:  188491 primos
         Exponentes de Mersenne: [7, 31, 127, 607, 1279, 4423, 110503]
Clase 11:  188497 primos
         Exponentes de Mersenne: [107, 86243]
Clase 13:  188452 primos
         Exponentes de Mersenne: [13, 61, 13466917]
Clase 17:  188566 primos
         Exponentes de Mersenne: [17, 89, 521, 9689, 19937, 859433, 3021377, 6972593]
Clase 19:  188459 primos
         Exponentes de Mersenne: [19, 2203, 216091, 1257787, 20996011]
Clase 23:  188357 primos
         Exponentes de Mersenne: [756839]
============================================================
Total de primos generados: 1507122
Exponentes de Mersenne encontrados:
[5, 7, 13, 17, 19, 31, 61, 89, 107, 127, 521, 607, 1279, 2203, 2281, 3217, 4253, 4423, 9689, 9941, 11213, 19937, 21701, 23209, 44497, 86243, 110503, 132049, 216091, 756839, 859433, 1257787, 1398269, 2976221, 3021377, 6972593, 13466917, 20996011]
Tiempo: 53.82 segundos

19 Agosto, 2026, 01:26 am
Respuesta #21

jhonny guanipa

  • $$\Large \color{#6a84c0}\pi$$
  • Mensajes: 13
  • País: ve
  • Karma: +0/-0
Hola buenas tardes, voy a compartirles un algoritmo que prepare y me gustaria que lo probaran y me compartieran los tiempos, les comento que en mi maquina uso el exponente de prueba m110503 y con mi maquina logro alcanzar los 10 segundos lo cual me parece muy eficiente ya que al principio tenia algoritmos que lo hacia en 65 segundos, con optimizaciones logre bajar a 16 segundos y alli me habia quedado un tiempo y llegue a pensar que era por mi maquina, pero ven que logre mejorar los tiempos aun mas. , mi equipo es una hp i7 de 11va generacion. La idea de compartir el algoritmo es ver si logran con un buen equipo llegar a tiempos de gimps los cual aunque dificil seria fabuloso. Lo que si agradeceria es que si le hacen mejoras lo compartan para seguir desarrollando. saludos cordiales a todos.

 [08:08, 14/8/2026] asofutlag competiciones: #include <iostream>
#include <cstdlib>
#include <gmp.h>
#include <omp.h>

// Estructura alineada a 64 bytes para eliminar el False Sharing entre núcleos de CPU
struct alignas(64) WorkerData {
    mpz_t v;       // Resultado del cuadrado
    mpz_t t_sum;   // Suma temporal para términos cruzados
};

void tdll_guanipa_v16_fast(int p) {
    int k = p / 3;

    mpz_t s, M, s0, s1, s2, s_next, temp_h, temp_l;
    mpz_t v01, v02, v12;

    mpz_inits(s, M, s0, s1, s2, s_next, temp_h, temp_l, v01, v02, v12, NULL);

    // PRE-ASIGNACIÓN DE MEMORIA: Clave para eliminar reallocs lentos en el bucle
    mpz_realloc2(s, p + 128);
    mpz_realloc2(M, p + 128);
    mpz_realloc2(s0, k + 128);
    mpz_realloc2(s1, k + 128);
    mpz_realloc2(s2, k + 128);
    mpz_realloc2(s_next, 2 * p + 128);
    mpz_realloc2(temp_h, p + 128);
    mpz_realloc2(temp_l, p + 128);
    mpz_realloc2(v01, 2 * k + 128);
    mpz_realloc2(v02, 2 * k + 128);
    mpz_realloc2(v12, 2 * k + 128);

    WorkerData workers[6];
    for (int i = 0; i < 6; i++) {
        mpz_init(workers.v);
        mpz_init(workers.t_sum);
        mpz_realloc2(workers.v, 2 * k + 128);
        mpz_realloc2(workers.t_sum, k + 128);
    }

    mpz_set_ui(s, 4);
    mpz_set_ui(M, 1);
    mpz_mul_2exp(M, M, p);
    mpz_sub_ui(M, M, 1);

    std::cout << "\n⚡ MOTOR GUANIPA V16 FAST-DIRECT | M" << p << " | 6 Hilos Persistentes\n";
    double start = omp_get_wtime();

    // POOL DE HILOS PERSISTENTE (Se crea una sola vez)
    #pragma omp parallel num_threads(6)
    {
        int tid = omp_get_thread_num();

        for (int i = 1; i <= p - 2; i++) {

            // Paso 1: División de s en 3 bloques (Hilo Maestro)
            #pragma omp single
            {
                mpz_tdiv_r_2exp(s0, s, k);
                mpz_tdiv_q_2exp(s_next, s, k);
                mpz_tdiv_r_2exp(s1, s_next, k);
                mpz_tdiv_q_2exp(s2, s_next, k);
            } // Barrera implícita: garantiza que s0, s1, s2 están listos para todos

            // Paso 2: Asignación ESTATICA de los 6 cuadrados (Cero sobrecosto de tareas)
            switch (tid) {
                case 0:
                    mpz_mul(workers[0].v, s0, s0); // v0
                    break;
                case 1:
                    mpz_mul(workers[1].v, s1, s1); // v1
                    break;
                case 2:
                    mpz_mul(workers[2].v, s2, s2); // v2
                    break;
                case 3:
                    mpz_add(workers[3].t_sum, s0, s1);
                    mpz_mul(workers[3].v, workers[3].t_sum, workers[3].t_sum); // v01
                    break;
                case 4:
                    mpz_add(workers[4].t_sum, s0, s2);
                    mpz_mul(workers[4].v, workers[4].t_sum, workers[4].t_sum); // v02
                    break;
                case 5:
                    mpz_add(workers[5].t_sum, s1, s2);
                    mpz_mul(workers[5].v, workers[5].t_sum, workers[5].t_sum); // v12
                    break;
            }

            #pragma omp barrier // Espera ultrarrápida por los 6 cuadrados

            // Paso 3: Reconstrucción PARALELA de términos cruzados
            switch (tid) {
                case 0:
                    mpz_sub_ui(s_next, workers[0].v, 2);
                    break;
                case 3:
                    mpz_sub(v01, workers[3].v, workers[0].v);
                    mpz_sub(v01, v01, workers[1].v);
                    break;
                case 4:
                    mpz_sub(v02, workers[4].v, workers[0].v);
                    mpz_sub(v02, v02, workers[2].v);
                    mpz_add(v02, v02, workers[1].v);
                    break;
                case 5:
                    mpz_sub(v12, workers[5].v, workers[1].v);
                    mpz_sub(v12, v12, workers[2].v);
                    break;
                default:
                    break;
            }

            #pragma omp barrier

            // Paso 4: Ensamblado y Reducción Fast-Mersenne (Hilo Maestro)
            #pragma omp single
            {
                mpz_mul_2exp(temp_l, v01, k);
                mpz_add(s_next, s_next, temp_l);

                mpz_mul_2exp(temp_l, v02, 2 * k);
                mpz_add(s_next, s_next, temp_l);

                mpz_mul_2exp(temp_l, v12, 3 * k);
                mpz_add(s_next, s_next, temp_l);

                mpz_mul_2exp(temp_l, workers[2].v, 4 * k); // v2
                mpz_add(s_next, s_next, temp_l);

                // Reducción modular rápida modulo (2^p - 1)
                mpz_tdiv_r_2exp(temp_l, s_next, p);
                mpz_tdiv_q_2exp(temp_h, s_next, p);
                mpz_add(s, temp_l, temp_h);

                if (mpz_cmp(s, M) >= 0) {
                    mpz_sub(s, s, M);
                }
            }
        }
    }

    double end = omp_get_wtime();

    if (mpz_cmp(s, M) == 0) mpz_set_ui(s, 0);

    std::cout << "🏁 RESULTADO: " << (end - start) << " seg | Popcount: "
              << mpz_popcount(s) << std::endl;

    // Limpieza de memoria
    for (int i = 0; i < 6; i++) {
        mpz_clear(workers.v);
        mpz_clear(workers.t_sum);
    }
    mpz_clears(s, M, s0, s1, s2, s_next, temp_h, temp_l, v01, v02, v12, NULL);
}

int main(int argc, char *argv[]) {
    int p = (argc > 1) ? atoi(argv[1]) : 110503;
    tdll_guanipa_v16_fast(p);
    return 0;
}
algoritmo tdll de 10 segundos.
g++ -O3 -march=native -fopenmp tdll_guanipa_v16_fast.cpp -lgmp -o tdll_v16
para compilar
./tdll_v16 110503