Büyük kovaryans matrislerinin paralel hesaplanması


9

ile arasında değişen boyutlarda kovaryans matrislerini hesaplamamız gerekir . GPU'lara ve kümelere erişebiliyoruz, bu hesaplamaları hızlandırmak için en iyi paralel yaklaşımın ne olduğunu merak ediyoruz.10000×10000100000×100000


1
Kovaryans matrisiniz için özellikler mi bekliyorsunuz? Örneğin, çok sayıda "0'a yakın" korelasyon?
Dr_Sam

Hayır, şu anda hiçbir şey bekleyemeyiz
yolu açın

Senin k nedir Yani, her veri vektörü ne kadardır? Zaten sıfır demek mi?
Max Hutchinson

hayır, sıfır ortalama değiller, her ne pahasına olursa olsun alabilirler
yolunu aç

3
@flow: '' klinik veriler '' appl8ication, ancak kullanımı değil. Sorum şuydu: Diyelim ki kovaryans matrisiniz var, onunla ne yapacaksınız (matematiksel açıdan)? Sormamın nedeni, sonunda her zaman ondan çok az hesaplaması ve eğer bu dikkate alınırsa, genellikle istenen sonucu elde ederken tam kovaryans matrisini hesaplamaktan kaçınarak şeyleri muazzam bir şekilde hızlandırabilir.
Arnold Neumaier

Yanıtlar:


17

İlk şey, BLAS kullanarak bunu yapabileceğinizi tanımaktır. Veri matrisiniz (her bir ölçüme karşılık gelen bir sütun vektörüdür; satırlar deneme niteliğindedir), o zaman yazabilirsiniz kovaryans şu şekilde: Bunu şu şekilde yazabiliriz: burada , tüm öğeleri 1 olan satır-vektörüdür, bu nedenle , sütun toplamlarının bir satır vektörüdür . Bu tamamen BLAS olarak yazılabilir, buradaX=[x1x2x3...]Rm×nx

Cij=E[xi,xj]E[xi]E[xj]=1nkxikxjk1n2(kxik)(kxjk)
C=1nXTX1n2(1TX)T(1TX)
(1T)(1TX)XXTXya da a, GEMM bir, daha iyisi, veya SYRK / HERK ve alabilirsiniz bir ile GEMV , tekrar GEMM veya SYRK / herk ile, ve ile eslestirmeler de ön çarpanları Scal .(1TX)=bbTb

Verileriniz ve sonuç matrisleriniz 64 GB civarında olabilir, bu nedenle tek bir düğüme veya bir düğümün değerinde GPU'ya sığmayacaksınız. GPU olmayan bir küme için, iskele gibi görünen PBLAS'a bakmak isteyebilirsiniz. GPU'lar için, çok düğümlü kütüphaneler henüz tam olarak orada değildir. Magma'nın altta yatan bir çeşit paralel BLAS uygulaması vardır, ancak kullanıcı dostu olmayabilir. CULA'nın henüz çok düğümlü olduğunu düşünmüyorum , ama bu göz kulak olacak bir şey. CUBLAS tek düğümlüdür .

Ayrıca, özellikle MPI hakkında bilginiz varsa ve bunu mevcut bir kod tabanına bağlamanız gerekiyorsa, paralelliğin kendiniz uygulamanızı şiddetle tavsiye ederim. Bu şekilde, CPU ve GPU BLAS arasında kolayca geçiş yapabilir ve verilerle tam olarak istediğiniz yerde başlayıp bitebilirsiniz. Birkaç MPI_ALLREDUCE çağrıdan daha fazlasına ihtiyacınız olmamalıdır .


Analiziniz ve ilgili BLAS fonksiyonlarının listesi için teşekkür ederiz. Cevabınızı okuduktan sonra bunları Scilab'ın (www.scilab.org) geliştirme sürümünde kovaryans matrisinin hesaplanmasını hızlandırmak ve optimize etmek için kullandım.
Stéphane Mottelet

Ancak, ne zaman kovaryansını hesaplama bu şekilde kullanarak katastrofik iptali tabi uyardı yakın olan , bakınız örn en.wikipedia.org/wiki/...E[xi,xj]E[xi]E[xj]
Stéphane Mottelet

1

@Max Hutchinson tarafından CUBlas ve Cuda Thrust ile verilen formülü uyguladım ve çevrimiçi ortak varyans hesaplama araçlarıyla karşılaştırdım. Benimki iyi sonuçlar üretiyor gibi görünüyor. Aşağıdaki kod QDA Bayes için planlandı. Dolayısıyla verilen matris birden fazla sınıf içerebilir. Böylece çoklu ko varyans matrisleri hesaplanır. Umarım birisi için faydalı olur.

//! Calculates one or more than one coVarianceMatrix given data.
//  There can be many classes since many covariance matrixes.
/*!
    \param inMatrix This vector contains matrix data in major storage. 
    Forexample if inMatrix=[1 2 3 4 5 6] and trialSizes=[2] this means matrix we will work on a matrix like :
        |1 4 |
        |2 5 |
        |3 6 | -> 2 Trials, 3 Features. Columns contains feature rows contains trials (samples)
    \param trialSizes There can be many classes since many covariance matrixes. Samples from all classes will be given with inMatrix.
    But we need to know how many trials(samples) we have for each class. 
    For example if inMatrix=[1 2 3 4 5 6 7 8 9 10 11 12] and trialSizes=[2,2] 
    this means matrix we will work on a matrix like :
        |1 4 |  |7 10 |
        |2 5 |  |8 11 |
        |3 6 |  |9 12 |  --> Total number of trials(samples which is total rowCount) 2 + 2 = 4 , 
                             So colSize = inMatrix.size()/4 = 3(feature vector size)
                         --> There is two element in trialSize vec so each vector has to samples
*/
void multiQDACovianceCalculator(std::vector<float>& inMatrix, std::vector<int>& trialSizes)
{
    cublasHandle_t handle; // CUBLAS context
    int classCount = trialSizes.size();
    int rowSize = std::accumulate(trialSizes.begin(), trialSizes.end(), 0);
    int dimensionSize = inMatrix.size() / rowSize;
    float alpha = 1.0f;
    float beta = 0.0f; // bet =1

    thrust::device_vector<float> d_cov1(dimensionSize * dimensionSize);
    thrust::device_vector<float> d_cov2(dimensionSize * dimensionSize);
    thrust::device_vector<float> d_covResult(dimensionSize * dimensionSize);

    thrust::device_vector<float> d_wholeMatrix(inMatrix);
    thrust::device_vector<float> d_meansVec(dimensionSize); // rowVec of means of trials
    float *meanVecPtr = thrust::raw_pointer_cast(d_meansVec.data());
    float *device2DMatrixPtr = thrust::raw_pointer_cast(d_wholeMatrix.data());
    auto maxTrialNumber = *std::max_element(trialSizes.begin(), trialSizes.end());
    thrust::device_vector<float> deviceVector(maxTrialNumber, 1.0f);

    cublasCreate(&handle);
    // Inside of for loop  one covariance matrix calculated each time
    for (int i = 0; i < trialSizes.size(); i++)
    {
        // X*transpose(X) / N
        alpha = 1.0f / trialSizes[i];
        cublasSgemm(handle, CUBLAS_OP_N, CUBLAS_OP_T, dimensionSize, dimensionSize, trialSizes[i], &alpha,
            device2DMatrixPtr, dimensionSize, device2DMatrixPtr, dimensionSize, &beta,
            thrust::raw_pointer_cast(d_cov1.data()), dimensionSize);

        // Mean vector of each column
        alpha = 1.0f;
        cublasSgemv(handle, CUBLAS_OP_N, dimensionSize, trialSizes[i], &alpha, device2DMatrixPtr,
            dimensionSize, thrust::raw_pointer_cast(deviceVector.data()), 1, &beta, meanVecPtr, 1);

        // MeanVec * transpose(MeanVec) / N*N
        alpha = 1.0f / (trialSizes[i] * trialSizes[i]);
        cublasSgemm(handle, CUBLAS_OP_T, CUBLAS_OP_N, dimensionSize, dimensionSize, 1, &alpha,
            meanVecPtr, 1, meanVecPtr, 1, &beta,
            thrust::raw_pointer_cast(d_cov2.data()), dimensionSize);

        alpha = 1.0f;
        beta = -1.0f;
        //  (X*transpose(X) / N) -  (MeanVec * transpose(MeanVec) / N*N)
        cublasSgeam(handle, CUBLAS_OP_N, CUBLAS_OP_N, dimensionSize, dimensionSize, &alpha,
            thrust::raw_pointer_cast(d_cov1.data()), dimensionSize, &beta, thrust::raw_pointer_cast(d_cov2.data()), 
            dimensionSize, thrust::raw_pointer_cast(d_covResult.data()), dimensionSize);

        // Go to other class and calculate its covarianceMatrix
        device2DMatrixPtr += trialSizes[i] * dimensionSize;
    }
    printVector(d_covResult);
    cublasDestroy(handle);
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.