Closed JJ closed 3 months ago
Ya está divididos los cuatro eventos. Ahora main queda de esta forma para todas las versiones:
int main(int argc, char *argv[])
{
population p(POPULATION_SIZE);
initialize(p);
mutate(p);
crossover(p);
return evaluate(p);
}
De aquí yo diría que lo único que queda pendiente es que sólo haya dos niveles: con generación y con una operación.
La función main se hizo común para todas las versiones. ¿Es necesario hacerle algún cambio más?
template<typename population> int common_main(int argc, char *argv[])
{
std::size_t step = std::numeric_limits<std::size_t>::max(), value = 0;
if (argc > 1)
step = std::atoi(argv[1]);
std::cout << "step = " << step << '\n';
if (step == 0)
return value;
population p(POPULATION_SIZE);
if (step == 1)
return value;
initialize(p);
if (step == 2)
return value;
mutate(p);
if (step == 3)
return value;
crossover(p);
if (step == 4)
return value;
value = evaluate(p);
return value;
}
La función main se hizo común para todas las versiones. ¿Es necesario hacerle algún cambio más?
template<typename population> int common_main(int argc, char *argv[]) { std::size_t step = std::numeric_limits<std::size_t>::max(), value = 0; if (argc > 1) step = std::atoi(argv[1]); std::cout << "step = " << step << '\n'; if (step == 0) return value; population p(POPULATION_SIZE); if (step == 1) return value; initialize(p); if (step == 2) return value; mutate(p); if (step == 3) return value; crossover(p); if (step == 4) return value; value = evaluate(p); return value; }
Sigue teniendo 4 niveles, no dos: uno para inicializar, otro para el resto. Además, como te comenté, no se trata de aplicar a todo el bucle una, luego otra, luego otra: un solo bucle, aplicar las tres operaciones.
Si da igual perder las mediciones individuales para mutación, cruce y evaluación se puede hacer. En todo caso debería haber como mínimo 3 fases para poder descartar la sobrecarga de inicialización y finalización de la biblioteca de c++. De esta forma quedaría: 0) libstdc++ 1) inicialización 2) AG
¿Te parece bien así?
La sobrecarga en la inicialización la descartamos restando de las medidas la media de inicialización de los cromosomas. Por tanto, una fase para inicialización. Pero tendría que haber dos programas: uno para evaluar sobre los 40000 cromosomas mutación + crossover + maxones y otra para HIFF. energy-languages-lion-2024.pdf Te adjunto lo que hicimos para LION18, y con lo que habría que comparar.
¿Te parece bien algo así?
template<typename chromosome> int common_main(int argc, char *argv[])
{
std::size_t step = std::numeric_limits<std::size_t>::max(), value = 0;
if (argc > 1)
step = std::atoi(argv[1]);
if (step == 0)
return value;
std::vector<chromosome> population(POPULATION_SIZE);
for (std::size_t i = 0; i < population.size(); i += 2)
{
initialize(population[i]);
initialize(population[i + 1]);
mutate(population[i]);
mutate(population[i + 1]);
crossover(population[i], population[i + 1]);
value += evaluate(population[i]) + evaluate(population[i + 1]);
}
return value;
}
¿Te parece bien algo así?
template<typename chromosome> int common_main(int argc, char *argv[]) { std::size_t step = std::numeric_limits<std::size_t>::max(), value = 0; if (argc > 1) step = std::atoi(argv[1]); if (step == 0) return value; std::vector<chromosome> population(POPULATION_SIZE); for (std::size_t i = 0; i < population.size(); i += 2) { initialize(population[i]); initialize(population[i + 1]);
La intención de este issue es que se pueda usar la inicialización de los cromosomas como medida base, que descuente no solo lo que tarda en sí esa inicialización sino también el fondo de overhead del ordenador. Por lo tanto, esta inicialización tendría que estar en su propio bucle, y el step tendría que terminar aquí.
El step 1 aplicaría los tres operadores a los cromosomas ya inicializados.
Si usas un PR puedo hacer sugerencias de código sobre el mismo que se pueden incorporar a la rama.
¿Qué es eso de PR?... Que soy muy nuevo en esto de git...
ya he sacado la inicialización a otro bucle
Lo he dejado en versiones de los ficheros acabados en 2 porque todavía no me llevo bien con las ramas. Falta implementar algunas de las versiones de HIFF e integrarlo, después cambiaré por las versiones definitivas.
¿Qué es eso de PR?... Que soy muy nuevo en esto de git...
Pull Request. Haces una rama, subes la rama, abres un pull request para que el resto de la gente examine la rama. A ver, nuevo, nuevo, tampoco, ¿no?
En todo caso, en los mensajes de commit puedes poner el número de este issue (#2) o el que sea para que enlacen directamente aquí (y notifiquen a quien participa en el issue)
Hace muchos años que no uso git de verdad, no solo para hacer clone.
Ya he integrado los cambios en main y hiff solo para la versión string... te dejo unos resultados:
gustavo@casa:~/escritorio/energy/c++$ make test
------------------------------------------------
program length energy(J) time(s)
------------------------------------------------
bitset 512 35,85 1,115925
bitset 1024 35,68 1,11629
bitset 2048 36,80 1,114279
dbitset 512 36,02 1,11707
dbitset 1024 36,71 1,11533
dbitset 2048 35,73 1,116086
string 512 34,35 1,102741
string 1024 33,79 1,101899
string 2048 34,58 1,102023
string-hiff 512 128,25 3,98274
string-hiff 1024 128,32 3,98507
string-hiff 2048 135,46 4,00595
vector 512 35,49 1,147702
vector 1024 37,26 1,15190
vector 2048 36,34 1,150709
Igual habría que hacer algún tipo de filtrado sobre qué se va a usar HIFF. En todo caso, estás metiendo en una tabla cosas diferentes... Y el resto de los resultados son muy parecidos, habría que ver analizando los resultados individuales si hay diferencia significativa. A priori, yo diría que la representación "no compacta", el string, tarda algo menos que el resto y consume menos energía. Pero habría que eliminar de ahí la "línea base" de generación de cromosomas.
¿Me puedes aclarar cual de los dos puntos de salida es el que te interesa?
std::size_t step = std::numeric_limits<std::size_t>::max(), value = 0;
if (argc > 1)
step = std::atoi(argv[1]);
if (step == 0)
return value;
std::vector<chromosome> population(POPULATION_SIZE);
for (std::size_t i = 0; i < population.size(); ++i)
initialize(population[i]);
if (step == 1)
return value;
for (std::size_t i = 0; i < population.size(); i += 2)
{
mutate(population[i]);
mutate(population[i + 1]);
crossover(population[i], population[i + 1]);
value += evaluate(population[i]) + evaluate(population[i + 1]);
}
return value;
he escogido el segundo y lo he simplificado de forma que ejecutar el programa pasando cualquier parámetro lo haga finalizar tras la inicialización:
template<typename chromosome> int common_main(int argc, char *argv[])
{
std::size_t value = 0;
std::vector<chromosome> population(POPULATION_SIZE);
for (std::size_t i = 0; i < population.size(); ++i)
initialize(population[i]);
if (argc != 1)
return value;
for (std::size_t i = 0; i < population.size(); i += 2)
{
mutate(population[i]);
mutate(population[i + 1]);
crossover(population[i], population[i + 1]);
value += evaluate(population[i]) + evaluate(population[i + 1]);
}
return value;
}
pequeña prueba:
gustavo@casa:~/escritorio/energy/c++$ make init
------------------------------------------------------------------------
program length opt energy(J) time(s) run
------------------------------------------------------------------------
bitset 512 -O2 8,65 0,263075802 1720092527
bitset 512 -O2 9,60 0,269661140 1720092528
bitset 512 -O2 8,90 0,266998451 1720092530
bitset 512 -O2 8,80 0,263896472 1720092531
bitset 512 -O2 8,60 0,263482812 1720092532
bitset 512 -O2 8,76 0,263880562 1720092533
bitset 512 -O2 8,95 0,267956750 1720092534
bitset 512 -O2 9,37 0,266702781 1720092535
bitset 512 -O2 8,84 0,266139041 1720092537
gustavo@casa:~/escritorio/energy/c++$ make full
------------------------------------------------------------------------
program length opt energy(J) time(s) run
------------------------------------------------------------------------
bitset 512 -O2 9,44 0,282508345 1720092542
bitset 512 -O2 9,35 0,282187066 1720092543
bitset 512 -O2 9,44 0,283340935 1720092544
bitset 512 -O2 9,44 0,282035216 1720092545
bitset 512 -O2 9,46 0,285881144 1720092546
Si puede ser, debería ser una función independiente que se incluyera en el main. Y ya puestos, me gusta testear todo. Si quieres puedo hacerlo yo, una vez que las funciones estén en su propio módulo.