"New Neural" es un proyecto de motor de red neuronal de código abierto para la plataforma MetaTrader 5. - página 59

 

Amigos, si decidís meteros con las GPUs, tened en cuenta lo siguiente. Es fácil paralelizar algoritmos de aprendizaje en los que una iteración es independiente de la otra. Por ejemplo, la genética, en la que el cálculo de cientos de redes en una generación no depende de las demás, Manhattan (enumeración muda de todas las soluciones), o la optimización de redes independientes en un comité. Pero estos algoritmos son pocos. Los métodos basados en el descenso de gradiente serían más difíciles de paralelizar porque una iteración depende de otra. En estos casos, sería necesario dividir el cálculo de las neuronas de la misma capa en hilos paralelos, lo que no siempre es trivial.

 

... Y la genética no forma parte de la red, sino que es un algoritmo externo independiente.

La gente aquí quiere redes paralelas.

 
Una cosa no excluye la otra.
 
TheXpert:

... Y la genética no forma parte de la red, sino que es un algoritmo externo independiente.

La gente aquí quiere paralizar las redes.

Escriba algo que funcione al principio y luego paralelícelo. El código de KUDav lleva mucho tiempo de depuración debido a los posibles errores: hay que saber cuánta memoria asignar a las diferentes matrices, escribir comandos para cargar y descargar estas matrices de la memoria, sincronizar los hilos, etc. Aquí hay un fragmento del código Kuda (1/20 del código completo). Tenga en cuenta que ninguno de los comandos está directamente relacionado con el algoritmo de aprendizaje de la red en sí. Para mí todo es chino.

#define SHARED_BUFFER_SIZE 512

#define MAX_DATA_SIZE 227

#define MAX_FILTER_33_SIZE 73

#define MAX_MASK_23_SIZE 27

#define MAX_MASK_34_SIZE 27

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

__constant__ float M33_Filter[ MAX_FILTER_33_SIZE ][ MAX_FILTER_33_SIZE ];

__constant__ float M23_Mask [ MAX_MASK_23_SIZE ][ MAX_MASK_23_SIZE ];

__constant__ float M34_Mask [ MAX_MASK_34_SIZE ][ MAX_MASK_34_SIZE ];

__shared__ float SharedBuf[ SHARED_BUFFER_SIZE ];

#define ALLIGN 32

#define ROUND_UP( val ) ( ( ( ( val ) + ALLIGN - 1 ) / ALLIGN ) * ALLIGN )

__host__ __device__ int Get2DIndex( int dataSize, int row, int col )

{

int dataSizeP = ROUND_UP( dataSize );

int idx = row * dataSizeP + col;

//assert( idx >= 0 && idx < dataSize * dataSizeP );

return idx;

}

__host__ __device__ float Get2D( float *data, int dataSize, int row, int col )

{

int idx = Get2DIndex( dataSize, row, col );

return data[ idx ];

}

__host__ __device__ void Set2D( float *data, int dataSize, int row, int col, float val )

{

int idx = Get2DIndex( dataSize, row, col );

data[ idx ] = val;

}

__host__ __device__ int Get4DIndex( int dataSize, int filtSize, int row, int col, int rowF, int colF )

{

int dataSizeP = ROUND_UP( dataSize );

int filtSizeP = ROUND_UP( filtSize );

int idx;

idx = row;

idx = idx * filtSizeP + rowF;

idx = idx * filtSizeP + colF;

idx = idx * dataSizeP + col;

//assert( idx >= 0 && idx < dataSize * dataSizeP * filtSizeP * filtSizeP );

return idx;

}

__host__ __device__ float Get4D( float *filt, int dataSize, int filtSize, int row, int col, int rowF, int colF )

{

int idx = Get4DIndex( dataSize, filtSize, row, col, rowF, colF );

return filt[ idx ];

}

__host__ __device__ void Set4D( float *filt, int dataSize, int filtSize, int row, int col, int rowF, int colF, float val )

{

int idx = Get4DIndex( dataSize, filtSize, row, col, rowF, colF );

filt[ idx ] = val;

}

__global__ void Calc_1_kernel( float* o2, float* i3, float* fi3, float* o3, float* o3tmp, float *w23, int n2, int n3, int n23, int h23, int ntot23, float a3 )

{

int numBlocks = gridDim.x;

int numThreads = blockDim.x;

int blockId = blockIdx.x;

int threadId = threadIdx.x;

///* DEBUG */for( int blockId = 0; blockId < numBlocks; ++blockId )

{

for( int i = blockId; i < n3; i += numBlocks )

{

///* DEBUG */for( int threadId = 0; threadId < numThreads; ++threadId )

{

// clear output

for( int j = threadId; j < n3; j += numThreads )

{

Set2D( fi3, n3, i, j, 0 );

}

}

__syncthreads();

// process 'n23' rows

for( int dx = 0; dx < n23; ++dx )

{

int x;

if( n2 == n3 )

{

x = i + dx - h23;

if( x < 0 ) x += n2;

if( x >= n2 ) x -= n2;

}

else

{

x = i + dx;

}

///* DEBUG */for( int threadId = 0; threadId < numThreads; ++threadId )

{

// read one row of input data to shared memory ( row 'x' )

int dj;

if( n2 == n3 )

{

dj = h23;

}

else

{

dj = 0;

}

for( int jj = threadId; jj < n2; jj += numThreads )

{

float o2Val = Get2D( o2, n2, x, jj );

SharedBuf[ jj + dj ] = o2Val;

}

if( n2 == n3 )

{

for( int dj = threadId; dj < h23; dj += numThreads )

{

SharedBuf[ dj ] = SharedBuf[ n2 + dj ];

}

for( int dj = threadId; dj < h23 + 1; dj += numThreads )

{

SharedBuf[ n2 + h23 + dj ] = SharedBuf[ h23 + dj ];

}

}

}

__syncthreads();

///* DEBUG */for( int threadId = 0; threadId < numThreads; ++threadId )

{

// filter one row

for( int j = threadId; j < n3; j += numThreads )

{

float fi3Val = Get2D( fi3, n3, i, j );

for( int dy = 0; dy < n23; ++dy )

{

float w23Val = Get4D( w23, n3, n23, i, j, dx, dy );

float o2Val = SharedBuf[ j + dy ];

fi3Val += o2Val * w23Val;

}

Set2D( fi3, n3, i, j, fi3Val );

}

}

__syncthreads();

}

__syncthreads();

 
gpwr:

Amigos, si decidís meteros con las GPUs, tened en cuenta lo siguiente. Es fácil paralelizar algoritmos de aprendizaje en los que una iteración es independiente de la otra. Por ejemplo, la genética, en la que el cálculo de cientos de redes en una generación no depende de las demás, Manhattan (enumeración muda de todas las soluciones), o la optimización de redes independientes en un comité. Pero estos algoritmos son pocos. Los métodos basados en el descenso de gradiente serían más difíciles de paralelizar porque una iteración depende de la otra. En estos casos, hay que dividir el cálculo de las neuronas de la misma capa en hilos paralelos, lo que no siempre es trivial.

En la GPU sólo podremos paralelizar cálculos sencillos, cálculos simples dentro de un ciclo, por lo que sería muy difícil (y dudo que sea efectivo) implementar cálculos de diferentes fases de la genética en la GPU.

La naturaleza de la aceleración de la GPU radica en la independencia de las entradas de las salidas dentro de la misma iteración y en la uniformidad de las operaciones (como señaló gpwr anteriormente). ¿No es eso muy parecido a la definición de capa que derivamos colegiadamente más arriba? Por eso sugerí distinguir la capa como el objeto principal de trabajo, y el objeto neurona sólo como una entidad informativa adjunta a la capa.

 
gpwr:

Escriba algo que funcione al principio y luego paralelícelo. El código KUDAW lleva mucho tiempo de depuración debido a los posibles errores: hay que saber cuánta memoria asignar a las diferentes matrices, escribir comandos para cargar y descargar estas matrices de la memoria, sincronizar los hilos, etc. Aquí hay un fragmento del código Kuda (1/20 del código completo). Tenga en cuenta que ninguno de los comandos está directamente relacionado con el algoritmo de aprendizaje de la red en sí. Para mí todo es chino.

...

Dichos fragmentos pueden marcarse a la vez dando nombres a las funciones con el apéndice "GPU" o marcarse con un comentario al principio de un bucle. Sólo para que la gente sepa que hay una posibilidad de utilizar el procesador de gráficos.

 
gpwr:

Escriba algo que funcione al principio y luego paralelícelo. El código KUDAV tarda mucho en ser depurado debido a los posibles errores: hay que saber cuánta memoria asignar a las diferentes matrices, escribir comandos para cargar y descargar estas matrices de la memoria, sincronizar hilos, etc. Aquí hay un fragmento del código Kuda (1/20 del código completo). Tenga en cuenta que ninguno de los comandos está directamente relacionado con el algoritmo de aprendizaje de la red en sí. Para mí todo es chino.

CUDA soporta SRF en toda su extensión.

Aquí está parte del código de hyp.tangent

#ifndef LAYER_TANH_H
#define LAYER_TANH_H

#ifndef CUDA
        #include <map>
        #include <boost/regex.hpp>
        extern std::map<std::string,int> mapObjects;
#endif
//---------------------------------------------------------------------------//
//                               CLayerTanh                                  //
//---------------------------------------------------------------------------//

namespace
#ifdef CUDA
        cuda
#else
        host
#endif
{

class CLayerTanh : public CLayerWSum
{
public:

#ifdef CUDA     
        __device__ static void run ( CLayer* layer )
        {
                CLayerTanh* L = static_cast<CLayerTanh*>(layer);
                if ( threadIdx.x < L->neuronCount )
                {
                        CLayerWSum::run(layer);
                        float * v = L->getNeuronPtr (threadIdx.x);
                        *v = tanh(*v);
                };
        }
#endif

};

} // namespace

#endif // LAYER_TANH

Es bueno que haya un experto en OpenCL aquí - un diálogo sustantivo y la discusión de las tecnologías beneficiará a todo el proyecto

Estoy seguro de que las redes neuronales se implementarán utilizando todas las tecnologías posibles (MQL5, C++, OpenCL, CUDA) y los usuarios podrán elegir según sus gustos y capacidades de hardware

 

Rebyata, ya budu seldom syuda zahodit'. Esli est' voprosi o interes k sovmestnim razrabotkami, pishite na moy yahoo email (ukazan v profile).

¡Buena suerte con el proyecto EngiNeuro!

 

Opciones para enviar ejemplos al algoritmo de aprendizaje:

  • Uno por uno
  • En grupos aleatorios
  • Grupos deslizantes
  • Todo a la vez

¿No te olvidas de nada?


He preparado un marco de proyecto, lo pondré a debate en un par de días...
 
Urain:

Opciones para enviar ejemplos al algoritmo de aprendizaje:

  • Uno por uno
  • Grupos aleatorios.
  • En grupos deslizantes.
  • Todo a la vez.

¿No te olvidas de algo?


Preparado el marco del proyecto, un par de días para agitar las cosas y ponerlo a debate...

De uno en uno, ya veo.

Y el resto de las opciones, no las entiendo. ¿Cómo puedo enviar todos los ejemplos a estudiar a la vez? - ¿O soy tonto?