Поэлементное векторно-векторное умножение в BLAS? - PullRequest
13 голосов
/ 01 октября 2011

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

Ответы [ 4 ]

10 голосов
/ 17 ноября 2012

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

Да, это можно сделать только с помощью 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]

7 голосов
/ 03 октября 2011

Всегда есть std :: valarray 1 , который определяет поэлементные операции, которые часто (Intel C ++ /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 Да, они архаичны и часто считаются устаревшими, но на практике они оба стандартны и очень хорошо подходят для этой задачи.

6 голосов
/ 03 октября 2011

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

5 голосов
/ 02 октября 2011

В GSL gsl_vector_mul делает свое дело.

...