La Instrucción `svld1_u8` en ARM SVE: Carga Vectorial de Datos de 8 bits

svuint8_t svld1_u8(
   svbool_t pg,               // Máscara de predicado: especifica qué elementos se cargan
   const uint8_t *base        // Dirección base: inicio de los datos contiguos en memoria
);

Descripción de Parámetros

  1. pg (máscara de predicado)
    Es un vector de máscara de tipo svbool\_t que determina qué posiciones dentro del vector SVE deben cargar datos válidos desde la memoria. Solo los elementos cuyo bit correspondiente en la máscara sea 1 se leerán; el resultado para las posiciones donde la máscara sea 0 es indefinido (aunque a menudo se ignoran o se rellenan con cero en la práctica).
    • La longitud de esta máscara se adapta a la anchura del vector SVE del hardware actual (por ejemplo, un vector de 128 bits para elementos de 8 bits tendría una máscara de 16 bits).
  2. base
    Puntero a la dirección inicial de los datos de tipo uint8\_t en memoria. La instrucción cargará datos de forma consecutiva a partir de esta dirección. El número de elementos cargados efectivamente es igual a la cantidad de bitts 1 en la máscara (o la longitud total del vector si todos los bits están activos).

Funcionalidad Principal

// Función para calcular la suma de los elementos de un array de uint8_t usando SVE. uint64_t calcular_suma_vectorial_u8(const uint8_t* datos_array, size_t longitud) { uint64_t suma_total = 0; size_t indice_actual = 0;

// Obtener la longitud de vector nativa (en bytes) para elementos de 8 bits.
// Esto determina cuántos elementos de uint8_t caben en un vector SVE.
svcount_t longitud_vector = svcntb();

// Inicializar la máscara de predicado para procesar los primeros elementos.
// La máscara indica qué elementos son válidos dentro del vector actual.
svbool_t mascara_activa = svwhilelt_b8(indice_actual, longitud);

// Bucle principal: continuar mientras haya elementos válidos marcados por la máscara.
// svptest_any(svptrue_b8(), mascara_activa) verifica si algún bit de la máscara está activo.
while (svptest_any(svptrue_b8(), mascara_activa)) {
    // Cargar un vector de 8 bits sin signo desde la memoria.
    // Solo los elementos correspondientes a los bits activos en 'mascara_activa'
    // serán cargados de 'datos_array + indice_actual'.
    svuint8_t vector_cargado = svld1_u8(mascara_activa, datos_array + indice_actual);

    // Sumar los elementos válidos del vector cargado.
    // svaddv_u8 acumula los valores de 'vector_cargado' donde 'mascara_activa' es 1.
    suma_total += svaddv_u8(mascara_activa, vector_cargado);

    // Avanzar el índice en la cantidad de elementos que se pueden procesar en un vector SVE.
    indice_actual += longitud_vector;

    // Actualizar la máscara para la siguiente iteración, considerando los elementos restantes.
    mascara_activa = svwhilelt_b8(indice_actual, longitud);
}
return suma_total;

}


### Consideraciones Clave

1. Escalabilidad de la Longitud del Vector   
    La longitud de los vectores SVE es flexible y dependiente del hardware (p. ej., 128, 256, 512 bits, etc.). `svld1\_u8` se ajusta automáticamente al ancho de vector soportado por el hardware en ejecución, eliminando la necesidad de especificar la longitud manualmente (la función `svcntb()` permite consultar la máxima longitud vectorial para elementos de 8 bits).
2. Función de la Máscara   
    Cuando la `longitud` del array no es un múltiplo exacto de la longitud del vector, la máscara `pg` es crucial. Se encarga de marcar solo los elementos que deben cargarse en el último bloque, previniendo accesos fuera de los límites de la memoria (por ejemplo, si `longitud=20` y `longitud\_vector=16`, la máscara en la última iteración solo tendrá los primeros 4 bits activos).
3. Compatibilidad con el Diseño de Memoria   
    `svld1\_u8` requiere que los datos estén dispuestos de forma contigua en memoria. Además, soporta accesos no alienados, lo que significa que no es estrictamente necesario que los datos estén alineados a la anchura del vector. No obstante, alinear los datos a límites de 8 bytes (`uint64\_t`) puede resultar en una mejora del rendimiento.
4. Diferencias con Otras Instrucciones de Carga 
    - `svld1\_u8` se usa para cargar datos contiguos, típicos en arrays o búferes de 8 bits.
    - Para cargar datos no contiguos (como en accesos indexados dispersos), se recurre a la serie de instrucciones `svld1\_gather`.
    - Si se requiere una carga con un desplazamiento específico o una carga parcial de un vector, se pueden emplear instrucciones como `svldl\_u8` (carga con longitud y desplazamiento).

Etiquetas: ARM SVE Intrinsics Vectorization SIMD svld1_u8

Publicado el 6-23 04:51