Алгоритм инкрементного обучения может изучать узлы и параметры сети одновременно, но с ростом структуры модели вычислительные затраты становятся все выше и выше, есть два способа уменьшить временные затраты на расчет: ( 1) Исследуйте метод разделения модели, разделите относительно большую модель на несколько более мелких подмоделей; (2) за счет повышения вычислительной мощности компьютера (GPU или CPU). TX2 может использовать CUDA для параллельных вычислений на графическом процессоре, а pycuda как библиотека параллельных вычислений для python может легко обеспечить параллельное ускорение на графическом процессоре. Эта статья использует pycuda для достижения параллельного ускорения и сравнивает его с numpy.
pycuda реализует параллельные вычисления
Учебники по установке и простому использованию см.официальный сайт пикуда.
простой пример
import pycuda.autoinit
import pycuda.driver as drv
import numpy as np
import time
from pycuda.compiler import SourceModule
mod = SourceModule('''
__global__ void Text_GPU(float *A , float *B, float *K, size_t N){
int bid = blockIdx.x;
int tid = threadIdx.x;
__shared__ float s_data[2];
s_data[tid] = (A[bid*2 + tid] - B[bid*2 + tid]);
__syncthreads();
if(tid == 0)
{
float sum_d = 0.0;
for(int i=0;i<N;i++)
{
sum_d += (s_data[i]*s_data[i]);
}
K[bid] = exp(-sum_d);
}
}
''')
multiply_them = mod.get_function("Text_GPU")
tic = time.time()
A = np.random.random((1000,20)).astype(np.float32)
B = np.random.random((1000,20)).astype(np.float32)
K = np.zeros((1000,), dtype=np.float32)
N = 20
N = np.int32(N)
multiply_them(
drv.In(A), drv.In(B), drv.InOut(K), N,
block=(20,1,1), grid=(1000,1))
toc = time.time()
print("time cost is:"+str(toc-tic))
time cost:0.00536298751831
Примечания
сетка и блок
Связь между блоками осуществляется через глобальную память (Global Memory), а потоки в одном блоке могут взаимодействовать друг с другом через общую память (Shared Memory). Каждому блоку потока соответствует своя собственная локальная память (Local Memory).
SourceModule
mod = SourceModule('''
__global__ void Text_GPU(.....){
......
}
''')
Этот код представляет собой функцию ядра C++, которая определяет основной код параллельных вычислений на графическом процессоре. Например: определите функцию ядра, которая добавляет два вектора
mod = SourceModule("""
__global__ void multiply_them(float *dest, float *a, float *b)
{
const int i = threadIdx.x;
dest[i] = a[i] + b[i];
}
""")
_shared_Переменная;
Определите общую память в том же блоке.
__syncthreads()
Функция синхронизации, когда приведенный выше код был выполнен в том же блоке, выполните код ниже функции синхронизации.
blockIdx.x и threadIdx.x
blockIdx.x принимает идентификатор блока, а threadIdx.x принимает идентификатор потока.
Сравнение с вычислениями numpy без ускорения GPU
Первый метод Numpy (не для цикла)
import numpy as np
import time
A = np.random.random((1000,20)).astype(np.float32)
B = np.random.random((1000,20)).astype(np.float32)
tic = time.time()
dk = A-B
dd = [np.sum(a**2) for a in dk]
K1 = np.exp(-np.array(dd))
toc = time.time()
print("time cost is:"+str(toc-tic))
time cost is:0.0174951553345
Второй метод Numpy (для цикла)
import numpy as np
import time
A = np.random.random((1000,20)).astype(np.float32)
B = np.random.random((1000,20)).astype(np.float32)
def Guassion_kernel(x, u):
d = x-u
dd = [np.sum(a**2) for a in d]
return np.exp(-sum(dd))
tic = time.time()
Phi_x = []
for j in range(1000):
Phi_x.append(Guassion_kernel(A[j], B[j]))
toc = time.time()
print("time cost is:"+str(toc-tic))
print(Phi_x)
time cost is:0.0264999866486
В сравнении
В таблице приведены расчетные затраты трех вышеуказанных методов. Видно, что затраты времени вычисления ускорения графического процессора самые низкие, а затраты времени вычисления цикла FOR самые высокие. Это только предварительное сравнение, в практических приложениях ускорение GPU иногда не быстрее, чем CPU. Когда объем данных невелик, а предварительная конфигурация с ускорением на GPU требует дополнительных вычислений, иногда время вычислений с ускорением на GPU больше, чем на CPU.
types | GPU | CPU without for loop | CPU with for loop |
---|---|---|---|
time cost | 0.00536298751831 | 0.0174951553345 | 0.0264999866486 |
Наконец, он применяется в инкрементном алгоритме, потому что количество узлов медленно увеличивается. Три способа расчета стоимости каждого шага итерации показаны на рисунке ниже. Мы обнаружили, что в начале операции количество узлов невелико, а стоимость вычислительного времени GPU выше, чем у CPU, но позже GPU и CPU (... Похоже, что GPU не имеет больших преимуществ , главным образом потому, что количество узлов все еще невелико, сотни узлов), я считаю, что с дальнейшим увеличением узлов эффективность GPU будет более заметной. | |||
## в заключении | |||
В этой статье рассказывается о pycuda и реализуются параллельные вычисления на GPU в python. |