Элементарное умножение векторных векторов в BLAS?

Есть ли способ сделать элементное векторное векторное умножение с BLAS, GSL или любой другой высокопроизводительной библиотекой?

Ответ 1

Я обнаружил, что MKL имеет целый набор математических операций над вектором в Библиотечной библиотеке математических функций (VML), включая v? Mul, который делает то, что я хочу. Он работает с массивами С++, поэтому для меня это более удобно, чем GSL.

Ответ 2

(Взяв название вопроса буквально...)

Да, это может быть сделано только с BLAS (хотя это, вероятно, не самый эффективный способ.)

Хитрость заключается в том, чтобы рассматривать один из входных векторов как диагональную матрицу:

⎡a    ⎤ ⎡x⎤    ⎡ax⎤
⎢  b  ⎥ ⎢y⎥ =  ⎢by⎥
⎣    c⎦ ⎣z⎦    ⎣cz⎦

Затем вы можете использовать одну из функций умножения матрицы-вектора, которые могут принимать диагональную матрицу в качестве входных данных без заполнения, например. SBMV

Пример:

void ebeMultiply(const int n, const double *a, const double *x, double *y)
{
    extern void dsbmv_(const char *uplo,
                       const int *n,
                       const int *k,
                       const double *alpha,
                       const double *a,
                       const int *lda,
                       const double *x,
                       const int *incx,
                       const double *beta,
                       double *y,
                       const int *incy);

    static const int k = 0; // Just the diagonal; 0 super-diagonal bands
    static const double alpha = 1.0;
    static const int lda = 1;
    static const int incx = 1;
    static const double beta = 0.0;
    static const int incy = 1;

    dsbmv_("L", &n, &k, &alpha, a, &lda, x, &incx, &beta, y, &incy);
}

// Test
#define N 3
static const double a[N] = {1,3,5};
static const double b[N] = {1,10,100};
static double c[N];

int main(int argc, char **argv)
{
    ebeMultiply(N, a, b, c);
    printf("Result: [%f %f %f]\n", c[0], c[1], c[2]);
    return 0;
}

Result: [1.000000 30.000000 500.000000]

Ответ 3

Всегда существует std:: valarray 1 который часто задает часто используемые операции (Intel С++ /Quse-intel-optimized-headers, g++), скомпилированные в инструкции SIMD, если цель поддерживает их.

Оба этих компилятора также будут выполнять автоинъекцию

В этом случае вы можете просто написать

#define N 10000 

float a[N], b[N], c[N]; 

void f1() { 
  for (int i = 1; i < N; i++) 
  c[i] = a[i] + b[i]; 
} 

и см. его компиляцию в векторизованный код (используя SSE4, например)

1 Да, они архаичны и часто считаются устаревшими, но на практике они являются стандартными и подходят к этой задаче очень хорошо.

Ответ 4

В GSL gsl_vector_mul делает трюк.