tan esencialmente que estás haciendo
k_0 = h_1 mod s
k_1 = h_1 + h_2 mod s = k_0 + h_2 mod s
k_2 = h_1 + h_2 + h_2 mod s = k_1 + h_2 mod s
..
k_n = k_(n-1) + h_2 mod s
Dependiendo de desbordamiento problemas (que no deberían diferir del original si el tamaño es menor que la mitad de 2**64
), esto podría ser más rápido (menos fácil de paralelizar):
uint64_t h_one = hash[0];
uint64_t h_two = hash[1];
k_hash[0] = h_one % size;
for (int i=1; i<k; ++i)
{
(uint64_t *) k_hash[i] = (k_hash[i-1] + h_two) % size;
}
Tenga en cuenta que existe la posibilidad de que su compilador ya haya llegado a este formulario, dependiendo de los indicadores de optimización que utilice.
Por supuesto, esto solo eliminó una multiplicación. Si desea eliminar o reducir el módulo, supongo que en base a h_two%size
y h_1%size
se puede predeterminar los pasos donde hay que llamar explícitamente %size
, algo como esto:
uint64_t h_one = hash[0]%size;
uint64_t h_two = hash[1]%size;
k_hash[0] = h_one;
step = (size-(h_one))/(h_two)-1;
for (int i=1; i<k; ++i)
{
(uint64_t *) k_hash[i] = (k_hash[i-1] + h_two);
if(i==step)
{
k_hash[i] %= size;
}
}
Nota No estoy seguro de la fórmula (no lo probó), es más una idea general. Esto dependería en gran medida de qué tan buena sea la predicción de sucursal (y de cuán grande sea el rendimiento: una predicción errónea). También es probable que ayude si el paso es grande.
edición: o más simple (y probablemente con el mismo rendimiento) -gracias a la mística:
uint64_t h_one = hash[0]%size;
uint64_t h_two = hash[1]%size;
k_hash[0] = h_one;
for (int i=1; i<k; ++i)
{
(uint64_t *) k_hash[i] = (k_hash[i-1] + h_two);
if(k_hash[i] > size)
{
k_hash[i] -= size;
}
}
¿Conoce usted algo de 'size'? – Mysticial
He editado la pregunta para aclarar algunas cosas, ya que exigió –
Existen métodos que hacen que las divisiones/módulos repetidos sobre el mismo número sean muy eficientes. Pero no es trivial. – Mysticial