Реализация LSTM с помощью theano scan, намного медленнее, чем использование циклов

Я использую Theano/Pylearn2 для реализации модели LSTM в моей собственной сети. Однако я обнаружил, что сканирование Theano намного, намного медленнее, чем использование простых циклов. Я использовал профилировщик Theano

<% time> <sum %> <apply time> <time per call> <type> <#call> <#apply> <Class name>
  95.4%    95.4%      25.255s       4.31e-02s     Py     586       3   theano.scan_module.scan_op.Scan
   1.8%    97.2%       0.466s       4.72e-05s     C     9864      41   theano.sandbox.cuda.basic_ops.GpuElemwise
   0.8%    97.9%       0.199s       8.75e-05s     C     2276      10   theano.sandbox.cuda.basic_ops.GpuAlloc
   0.7%    98.7%       0.196s       1.14e-04s     C     1724       8   theano.sandbox.cuda.blas.GpuDot22
   0.3%    99.0%       0.087s       1.06e-04s     C      828       3   theano.sandbox.cuda.basic_ops.GpuIncSubtensor
   0.2%    99.2%       0.051s       1.66e-04s     Py     310       2   theano.sandbox.cuda.basic_ops.GpuAdvancedSubtensor1

и Ops,

<% time> <sum %> <apply time> <time per call> <type> <#call> <#apply> <Op name>
  77.2%    77.2%      20.433s       7.40e-02s     Py     276        1   forall_inplace,gpu,grad_of_lstm__layers}
  18.2%    95.4%       4.822s       1.56e-02s     Py     310        2   forall_inplace,gpu,lstm__layers}

Так много и много времени уходит на сканирование (что вроде как и ожидалось, но я не ожидал, что это будет слишком медленно).

Основная часть моего кода

        def fprop(self, state_below, state_prev = 0, cell_prev = 0):
            if state_prev == None:
              state_prev = self.state_prev;
            if cell_prev == None:
              cell_prev = self.cell_prev;
            i_gate = T.nnet.sigmoid(T.dot(state_below,self.Wi) +
                                                            T.dot(state_prev,self.Ui));
            f_gate = T.nnet.sigmoid(T.dot(state_below,self.Wf) +
                                                            T.dot(state_prev,self.Uf));
            C = T.tanh(T.dot(state_below, self.Wc) +
                               T.dot(state_prev, self.Uc));
            C = i_gate * C + f_gate  * cell_prev;
            o_gate = T.nnet.sigmoid(T.dot(state_below,self.Wo) +
                                                            T.dot(state_prev,self.Uo) +
                                                            T.dot(C, self.Vo));
            h_out = o_gate * T.tanh(C);
            return h_out, C

И я написал свой скан как:

[h,c,out], _ = theano.scan(fn=self.fprop_with_output,
               sequences=[X.T,Y[:,1:].T],
               outputs_info=[dict(initial=h_,taps=[-1]), dict(initial=c_,taps=[-1]),None],n_steps=X.shape[1]-1);

Одна вещь, которую я заметил, заключается в том, что тип сканирования Theano использует реализацию Python (?) В том, что причина этого смехотворно медленная? или я что то не так сделал? Почему в Theano Python используется реализация Scan вместо C?

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

2 ответа

Это было задано некоторое время назад, но у меня была / есть та же проблема. Ответ в том, что сканирование на GPU идет медленно.

Смотрите: https://github.com/Theano/Theano/issues/1168

Разработчикам Theano требуется время, чтобы реализовать сканирование и градиент сканирования с использованием C и GPU, потому что это намного сложнее, чем другие функции. Вот почему при профилировании он показывает GpuElemwise, GpuGemv, GpuDot22 и т. Д., Но вы не видите GpuScan или GpuGradofScan.

Между тем, вы можете использовать только петли.

Другие вопросы по тегам