Chúng ta cần tính toán ma trận hiệp phương sai với các kích thước từ đến 100000 × 100000 . Chúng tôi có quyền truy cập vào GPU và cụm, chúng tôi tự hỏi đâu là cách tiếp cận song song tốt nhất để tăng tốc các tính toán này.
Chúng ta cần tính toán ma trận hiệp phương sai với các kích thước từ đến 100000 × 100000 . Chúng tôi có quyền truy cập vào GPU và cụm, chúng tôi tự hỏi đâu là cách tiếp cận song song tốt nhất để tăng tốc các tính toán này.
Câu trả lời:
Dữ liệu và ma trận kết quả của bạn có thể vào khoảng 64 GB, do đó bạn sẽ không vừa với một nút hoặc giá trị GPU của một nút. Đối với cụm không phải GPU, bạn có thể muốn xem PBLAS , cảm giác giống như scalapack. Đối với GPU, các thư viện đa nút chưa hoàn toàn ở đó. Magma có một số loại triển khai BLAS song song cơ bản, nhưng nó có thể không thân thiện với người dùng. Tôi không nghĩ CULA thực hiện đa nút, nhưng đây là điều cần chú ý. CUBLAS là một nút đơn.
Tôi cũng đề nghị bạn nên cân nhắc việc thực hiện song song chính mình, đặc biệt nếu bạn đã quen thuộc với Bộ KH & ĐT và phải nối cái này vào một cơ sở mã hiện có. Bằng cách đó, bạn có thể dễ dàng chuyển đổi giữa CPU và GPU BLAS và bắt đầu và kết thúc với dữ liệu chính xác nơi bạn muốn. Bạn không cần nhiều hơn một vài cuộc gọi MPI_ALLREDUCE .
Tôi đã triển khai công thức được đưa ra bởi @Max Hutchinson với CUBlas và Cuda Thrust và so sánh với các công cụ tính toán phương sai đồng trực tuyến. Có vẻ như tôi tạo ra kết quả tốt. Mã dưới đây được lên kế hoạch cho QDA Bayes. Vì vậy, ma trận đưa ra có thể chứa nhiều hơn một lớp. Vì vậy, nhiều ma trận phương sai co được tính toán. Tôi hy vọng nó sẽ hữu ích cho một ai đó.
//! 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);
}