2013-10-30 20 views
10

Il ciclo è abbastanza semplice, ma non riesco a spiegarmi come usare gli algoritmi STL per fornire lo stesso ciclo annidato in basso.Come riscrivere un ciclo annidato usando gli algoritmi C++ STL?

const int a_size = 5; // input 
const int c_size = 2; // output 
const int b_size = a_size * c_size; // multipliers 

std::vector<float> a(a_size); 
std::vector<float> b(b_size); 
std::vector<float> c(c_size); 

// fill a and b with data 

// this nested loop 
for(int i = 0; i<c_size; i++) { 
    c[i] = 0.0; 
    for(int k = 0; k<a_size; k++) { 
     c[i] += (a[k] * b[i*a_size+k]); 
    } 
    c[i] = sigmoid(c[i]); 
} 

Il motivo per cui mi piacerebbe fare questo, è per la biblioteca Boost.Compute, che avrebbe fatto i calcoli sulla GPU utilizzando algoritmi STL-simile (std :: trasformare, std :: for_each, ecc .).

+4

Sembra che si possa riscrivere l'algoritmo utilizzando le operazioni con le matrici. –

+1

Penso che sia meglio consentire agli utenti di scrivere kernel arbitrari in "Boost.Compute" - sarà molto più utile. Ad esempio tramite il metodo ['TaskGraph'] (http://ideone.com/qQ4Pvo) che ho descritto [qui] (http://boost.2283326.n4.nabble.com/compute-GPGPU-Library-Request-For -Feedback-tp4643691p4643927.html). –

risposta

6

mi è venuta with:

auto i = 0; 
generate(begin(c), end(c), [&i, &a, &b] 
{ 
    return sigmoid(inner_product 
    (
     begin(a), end(a), 
     begin(b) + distance(begin(a), end(a)) * i++, 0.f 
    )); 
}); 

Ma non sembra abbastanza bene - probabilmente in questo caso preferirei di scrivere il mio algoritmo.

Oppure utilizzare la matrice. Con la libreria Eigen diventerà:

MatrixXd b; 
VectorXd a, c; 
// ... 
c = (b*a).unaryExpr(sigmoid); 
+0

Mi ci vorrà un po 'per digerirlo. Mai sentito parlare di Eigen, supporta i calcoli sulla GPU? – user1973386

+1

@ user1973386 AFAIK - per il momento non supporta GPU. Anche se fa vettorizzazione tramite intrinseca (SSE2, ecc.). Ho appena trovato la seguente cosa: ['gpumatrix'] (https://github.com/rudaoshi/gpumatrix) -" * Una libreria di matrici e array su GPU con interfaccia compatibile con Eigen * "- Penso che valga la pena di guardare troppo . –

+0

Peccato che non supporti ancora OpenCL, ma è pianificato. Terrò traccia di quella libreria :). – user1973386

7

infatti il ​​ciclo annidato è algoritmo std :: inner_product.

auto first = std::begin(b); 
auto increment = std::distance(std::begin(a), std::end(a)); 
//,, 

c[i] = std::inner_product(std::begin(a), std::end(a), first, 0); 
std::advance(first, increment); 

Invece del ciclo esterno è possibile utilizzare l'algoritmo std :: generate.

Problemi correlati