"New Neural", MetaTrader 5 platformu için bir sinir ağı motorunun Açık Kaynak projesidir. - sayfa 59

 

Arkadaşlar, GPU ile uğraşmaya karar verirseniz, aşağıdakileri göz önünde bulundurun. Bir yinelemenin diğerine bağlı olmadığı öğrenme algoritmalarını paralel hale getirmek kolaydır. Örneğin, bir nesildeki yüzlerce ağın hesaplanmasının birbirine bağlı olmadığı genetik, Manhattan (tüm çözümlerin açık bir şekilde numaralandırılması) veya komitedeki bağımsız ağların optimizasyonu. Ancak bu tür birkaç algoritma var. Bir yineleme diğerine bağlı olduğundan, gradyan iniş yöntemlerinin paralelleştirilmesi daha zor olacaktır. Bu gibi durumlarda, aynı katmandaki nöronların hesaplamalarını, her zaman önemsiz olmayan paralel akışlara bölmek gerekecektir.

 

... Ve genetik, ağın ayrılmaz bir parçası değil, ayrı bir harici algoritmadır.

Burada ağın insanları paralelleşmek istiyor.

 
Müdahale etmez.
 
TheXpert :

... Ve genetik, ağın ayrılmaz bir parçası değil, ayrı bir harici algoritmadır.

Burada ağın insanları paralelleşmek istiyor.

Önce işe yarayan bir şey yazın ve sonra paralel hale getirin. NEREDE olası hatalar nedeniyle kodun uzun süre hata ayıklandığı: burada farklı dizilere ne kadar bellek ayrılacağını, bu dizileri bellekten yüklemek ve boşaltmak için komutlar yazmanız, iş parçacığı senkronizasyonu vb. bilmeniz gerekir. İşte kud kodunun bir parçası (tüm kodun 1/20'si). Tek bir komutun ağ öğrenme algoritmasının kendisiyle doğrudan bir ilişkisi olmadığını unutmayın. Benim için hepsi Çinli.

#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 :

Arkadaşlar, GPU ile uğraşmaya karar verirseniz, aşağıdakileri göz önünde bulundurun. Bir yinelemenin diğerine bağlı olmadığı öğrenme algoritmalarını paralel hale getirmek kolaydır. Örneğin, bir nesildeki yüzlerce ağın hesaplanmasının birbirine bağlı olmadığı genetik, Manhattan (tüm çözümlerin açık bir şekilde numaralandırılması) veya komitedeki bağımsız ağların optimizasyonu. Ancak böyle birkaç algoritma var. Bir yineleme diğerine bağlı olduğundan, gradyan iniş yöntemlerinin paralelleştirilmesi daha zor olacaktır. Bu gibi durumlarda, aynı katmandaki nöronların hesaplamalarını, her zaman önemsiz olmayan paralel akışlara bölmek gerekecektir.

GPU'da sadece basit hesaplamaları, basit hesaplamaları bir döngü içinde paralel yapmak mümkün olacak, bu yüzden farklı FF genetiği hesaplamasını GPU altında uygulamak çok zor olacak (ve etkili olacağından şüpheliyim).

GPU'daki hızlandırmanın doğası, bir yineleme içindeki girdilerin çıktılardan bağımsız olması ve işlemlerin tekdüzeliğinde (yukarıda gpwr belirtildiği gibi) yatar. Yukarıda kolektif olarak çıkardığımız katman tanımına çok benzemiyor mu? Bu nedenle, katmanı ana çalışma nesnesi olarak ve nöron nesnesini yalnızca katmana bağlı bilgisel bir varlık olarak seçmeyi önerdim.

 
gpwr :

Önce işe yarayan bir şey yazın ve sonra paralel hale getirin. NEREDE olası hatalar nedeniyle kodun uzun süre hata ayıklandığı: burada farklı dizilere ne kadar bellek ayrılacağını, bu dizileri bellekten yüklemek ve boşaltmak için komutlar yazmanız, iş parçacığı senkronizasyonu vb. bilmeniz gerekir. İşte kud kodunun bir parçası (tüm kodun 1/20'si). Tek bir komutun ağ öğrenme algoritmasının kendisiyle doğrudan bir ilişkisi olmadığını unutmayın. Benim için hepsi Çinli.

...

Yani kimse buna karşı değil, sıralı kod yazıp hatalarını ayıklayacağız, sadece koddaki bazı bölümleri paralelleştirme olasılığını savunuyorum. bu tür bölümler, "GPU" eklenerek işlev adları verilerek veya döngünün başında bir açıklama ile belirtilebilir. İnsanlar bilsin diye, işte grafiği kullanma imkanı. işlemci.

 
gpwr :

Önce işe yarayan bir şey yazın ve sonra paralel hale getirin. NEREDE olası hatalar nedeniyle kodun uzun süre hata ayıklandığı: burada farklı dizilere ne kadar bellek ayrılacağını, bu dizileri bellekten yüklemek ve boşaltmak için komutlar yazmanız, iş parçacığı senkronizasyonu vb. bilmeniz gerekir. İşte bir kudovsky kodu parçası (tüm kodun 1/20'si). Tek bir komutun ağ öğrenme algoritmasının kendisiyle doğrudan bir ilişkisi olmadığını unutmayın. Benim için hepsi Çinli.

CUDA, OPP'yi tamamen destekler

İşte hyp.tangent kodunun bir parçası

 #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

Burada bir OpenCL uzmanının olması iyi bir şey - kapsamlı bir diyalog ve teknolojilerin tartışılması tüm projeye fayda sağlayacaktır.

Yapay sinir ağlarının tüm olası teknolojiler (MQL5, C++, OpenCL, CUDA) için uygulanacağından ve kullanıcıların zevklerine ve donanım yeteneklerine göre seçim yapacaklarından eminim.

 

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

EngiNeuro projesinde iyi şanslar!

 

Öğrenme algoritmasına örnek verme seçenekleri:

  • parça tarafından
  • rastgele gruplar
  • sürgülü gruplar
  • Hepsi birden

Hiçbir şey unutmadın mı?


Projenin iskeletini hazırladım, birkaç gün içinde kararlaştırıp tartışmaya açacağım...
 
Ukrayna :

Öğrenme algoritmasına örnek verme seçenekleri:

  • parça tarafından
  • rastgele gruplar
  • sürgülü gruplar
  • Hepsi birden

Hiçbir şey unutmadın mı?


Projenin iskeletini hazırladım, birkaç gün içinde kararlaştırıp tartışmaya açacağım...

Bu arada - anlıyorum.

Ve diğer seçenekler - anlamadım. Tüm örnekleri bir kerede eğitim için nasıl başvurabilirim? - yoksa aptal mı?