Changeset 4d6a228


Ignore:
Timestamp:
Jan 16, 2019, 11:41:05 PM (6 years ago)
Author:
Paul Brossier <piem@piem.org>
Branches:
feature/crepe_org
Children:
591f077
Parents:
ec3f4d63
Message:

[conv2d] add simple blas version (im2row + gemm)

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/ai/conv2d.c

    rec3f4d63 r4d6a228  
    4545  uint_t output_shape[3];     // shape of output
    4646  uint_t padding_start[2];    // {top, left} padding
     47
     48#if defined(HAVE_BLAS)
     49  aubio_tensor_t *padded_input;
     50#endif
    4751};
    4852
     
    8589  if (c->bias)
    8690    del_fvec(c->bias);
     91#if defined(HAVE_BLAS)
     92  if (c->padded_input)
     93    del_aubio_tensor(c->padded_input);
     94#endif
    8795  AUBIO_FREE(c);
    8896}
     
    110118  uint_t output_shape[3] = {0, 0, c->n_filters};
    111119  uint_t padding_start[2] = {0, 0};
     120  // total amount of padding
     121  uint_t padding_shape[2] = {0, 0};
    112122
    113123  // check input parameters
     
    128138          / (smpl_t)c->stride_shape[1]);
    129139
    130       uint_t padding_shape[2];  // total amount of padding
    131140      padding_shape[0] = (output_shape[0] - 1) * c->stride_shape[0]
    132141        + c->kernel_shape[0] - input_tensor->shape[0];
     
    180189  shape[1] = output_shape[1];
    181190  shape[2] = output_shape[2];
     191
     192
     193#if defined(HAVE_BLAS)
     194  // im2col padding
     195  padding_shape[0] = output_shape[0] * output_shape[1];
     196  padding_shape[1] = c->kernel_shape[0] * c->kernel_shape[1]
     197    * input_tensor->shape[2];
     198  c->padded_input = new_aubio_tensor(2, padding_shape);
     199  if (!c-> padded_input) {
     200    AUBIO_MSG("conv2d: failed creating padded_input with shape (%d, %d, %d)\n",
     201        padding_shape);
     202    return AUBIO_FAIL;
     203  }
     204#endif
    182205
    183206  aubio_conv2d_debug(c, input_tensor);
     
    232255}
    233256
     257#if !defined(HAVE_BLAS)
    234258void aubio_conv2d_do(aubio_conv2d_t *c, aubio_tensor_t *input_tensor,
    235259    aubio_tensor_t *activations)
     
    301325}
    302326
     327#else /* HAVE_BLAS */
     328
     329void aubio_conv2d_copy_to_padded(aubio_conv2d_t *o,
     330    aubio_tensor_t *input_tensor, aubio_tensor_t *padded_input)
     331{
     332  // naive implementation of im2col
     333  uint_t i, j, k, l, m;
     334  uint_t stride_4 = o->kernel->shape[2];
     335  uint_t stride_3 = o->kernel->shape[1] * stride_4;
     336  uint_t stride_2 = o->kernel->shape[0] * stride_3;
     337  uint_t stride_1 = o->output_shape[1] * stride_2;
     338  uint_t stride_in_2 = input_tensor->shape[2];
     339  uint_t stride_in_1 = input_tensor->shape[1] * stride_in_2;
     340
     341  AUBIO_ASSERT(padded_input->size ==
     342      o->output_shape[0] * o->output_shape[1]
     343      * o->kernel_shape[0] * o->kernel_shape[1]
     344      * input_tensor->shape[2]);
     345  AUBIO_ASSERT(input_tensor->shape[2] == o->kernel->shape[2]);
     346
     347  for (i = 0; i < o->output_shape[0]; i++)
     348  {
     349    for (j = 0; j <  o->output_shape[1]; j++)
     350    {
     351      for (k = 0; k < o->kernel->shape[0]; k++)
     352      {
     353        for (l = 0; l < o->kernel->shape[1]; l++)
     354        {
     355          for (m = 0; m < o->kernel->shape[2]; m++)
     356          {
     357            uint_t read_i = i * o->stride_shape[0] + k;
     358            uint_t read_j = j * o->stride_shape[1] + l;
     359            if (read_i < o->padding_start[0])
     360              continue;
     361            else if (read_i - o->padding_start[0] >= input_tensor->shape[0])
     362              continue;
     363            if (read_j < o->padding_start[1])
     364              continue;
     365            else if (read_j - o->padding_start[1] >= input_tensor->shape[1])
     366              continue;
     367
     368            sint_t idx =
     369              ((read_i - o->padding_start[0])) * stride_in_1
     370              + ((read_j - o->padding_start[1])) * stride_in_2
     371              + m;
     372            padded_input->buffer[i * stride_1
     373              + j * stride_2
     374              + k * stride_3
     375              + l * stride_4
     376              + m]
     377              = input_tensor->buffer[idx];
     378          }
     379        }
     380      }
     381    }
     382  }
     383}
     384
     385void aubio_conv2d_do(aubio_conv2d_t *o, aubio_tensor_t *input_tensor,
     386    aubio_tensor_t *activations)
     387{
     388  uint_t i, j;
     389  smpl_t bias;
     390  aubio_tensor_t *padded_input = o->padded_input;
     391  aubio_tensor_t *kernel = o->kernel;
     392
     393  AUBIO_ASSERT(o && input_tensor && activations);
     394  // check we have the correct output activation sizes
     395  if (aubio_conv2d_check_output_shape(o, input_tensor, activations))
     396  {
     397    AUBIO_ERR("conv2d: check_output_shape failed\n");
     398    return;
     399  }
     400
     401  uint_t M = padded_input->shape[0];
     402  uint_t K = padded_input->size/padded_input->shape[0];
     403  uint_t N = kernel->size / K;
     404
     405  // check sizes
     406  AUBIO_ASSERT(M * K == padded_input->size);
     407  AUBIO_ASSERT(N * K == kernel->size);
     408  AUBIO_ASSERT(M * N == activations->size);
     409
     410  // copy input to im2col sliding window version
     411  aubio_conv2d_copy_to_padded(o, input_tensor, padded_input);
     412
     413  aubio_cblas__gemm(CblasRowMajor, CblasNoTrans, CblasNoTrans,
     414      M,                    // M
     415      N,                    // N
     416      K,                    // K
     417      1.F,                  // alpha
     418      padded_input->buffer, // M x K matrix
     419      K,                    // K (2nd dim of A)
     420      kernel->buffer,       // K x N matrix
     421      N,                    // N
     422      0.F,                  // beta
     423      activations->buffer,  // M x N matrix
     424      N);                   // N (2nd dim of C)
     425
     426
     427  // apply bias
     428  for (i = 0; i < activations->shape[2]; i++) {
     429    bias = o->bias->data[i];
     430    for (j = 0; j < activations->shape[0] * activations->shape[1]; j++)
     431    {
     432      activations->buffer[j * activations->shape[2] + i] += bias;
     433    }
     434  }
     435}
     436#endif
     437
    303438void aubio_conv2d_do_backwards(aubio_conv2d_t *c,
    304439    /*aubio_tensor_t *old_gradients,*/
Note: See TracChangeset for help on using the changeset viewer.