का उपयोग कर एकाधिक एसवीडी के लिए समांतर कार्यान्वयन मैं जीपीयू का उपयोग कर समानांतर प्रोग्रामिंग के लिए नया हूं इसलिए यदि प्रश्न व्यापक या अस्पष्ट है तो मैं क्षमा चाहता हूं। मुझे पता है कि सीयूएलए लाइब्रेरी में कुछ समानांतर एसवीडी फ़ंक्शन है, लेकिन यदि मेरे पास कारक बनाने के लिए अपेक्षाकृत छोटी मैट्रिक्स की बड़ी संख्या है तो रणनीति क्या होनी चाहिए? उदाहरण के लिए मेरे पास n
आयाम d
, n
के साथ matrices बड़े हैं और d
छोटा है। इस प्रक्रिया को समानांतर कैसे करें? क्या कोई मुझे संकेत दे सकता है?सीयूडीए
सीयूडीए
उत्तर
आप अपनी समस्या की चर्चा के लिए CULA ब्लॉग के Batched Operations पोस्ट पर एक नज़र डाल सकते हैं।
संपादित
मैं क्या नीचे अपनी टिप्पणी से समझ में से, आप प्रत्येक थ्रेड एक अलग SVD गणना करने के लिए करना चाहते हैं। इसलिए, मूल रूप से प्रत्येक थ्रेड को मानक, अनुक्रमिक एसवीडी योजना निष्पादित करनी चाहिए। उसके लिए कुछ संभवतः उपयोगी संदर्भ:
Golub, Van Loan, Matrix Computations
आप यह तरीका अपनाते हैं, हालांकि, मुझे डर है कि तुम अब और सक्षम cuBLAS उपयोग करने के लिए नहीं होगा हूँ, के रूप में उन host
कार्यों प्रतिदेय नहीं हैं device
से (जब तक आपके पास गणना क्षमता >3.5
नहीं है, तो simpleDevLibCUBLAS
उदाहरण देखें।)। लेकिन मूल रूप से मुझे लगता है कि आप किसी भी तरह से बैच अवधारणा को अपने आप लागू कर रहे हैं। बाहर का तारीख
मेरे पिछले जवाब है:
आप एक अधिक मानक समानांतर GPU कार्यान्वयन के लिए जाने का निर्णय तो नीचे दिए गए संदर्भ ब्याज की हो सकता है। फरवरी 2015 तक, सीयूडीए 7 (वर्तमान में रिलीज उम्मीदवार संस्करण में) अपनी एसयूएसओएलवीआर लाइब्रेरी में पूर्ण एसवीडी क्षमताओं की पेशकश करता है। नीचे, मैं CUDA CuSOLVER का उपयोग करके एकवचन मूल्य अपघटन उत्पन्न करने का एक उदाहरण प्रदान कर रहा हूं।
आपके द्वारा उठाए जा रहे विशिष्ट मुद्दे के बारे में (छोटे आकार के कई मैट्रिक्स के एसवीडी की गणना करना), आपको धाराओं का उपयोग करके नीचे प्रदान कर रहे उदाहरण को अनुकूलित करना चाहिए। प्रत्येक कार्य के लिए एक धारा संबद्ध करने के
cudaStreamCreate()
और
cusolverDnSetStream()
kernel.cu
#include "cuda_runtime.h"
#include "device_launch_parameters.h"
#include<iostream>
#include<iomanip>
#include<stdlib.h>
#include<stdio.h>
#include<assert.h>
#include<math.h>
#include <cusolverDn.h>
#include <cuda_runtime_api.h>
#include "Utilities.cuh"
/********/
/* MAIN */
/********/
int main(){
// --- gesvd only supports Nrows >= Ncols
// --- column major memory ordering
const int Nrows = 7;
const int Ncols = 5;
// --- cuSOLVE input/output parameters/arrays
int work_size = 0;
int *devInfo; gpuErrchk(cudaMalloc(&devInfo, sizeof(int)));
// --- CUDA solver initialization
cusolverDnHandle_t solver_handle;
cusolverDnCreate(&solver_handle);
// --- Setting the host, Nrows x Ncols matrix
double *h_A = (double *)malloc(Nrows * Ncols * sizeof(double));
for(int j = 0; j < Nrows; j++)
for(int i = 0; i < Ncols; i++)
h_A[j + i*Nrows] = (i + j*j) * sqrt((double)(i + j));
// --- Setting the device matrix and moving the host matrix to the device
double *d_A; gpuErrchk(cudaMalloc(&d_A, Nrows * Ncols * sizeof(double)));
gpuErrchk(cudaMemcpy(d_A, h_A, Nrows * Ncols * sizeof(double), cudaMemcpyHostToDevice));
// --- host side SVD results space
double *h_U = (double *)malloc(Nrows * Nrows * sizeof(double));
double *h_V = (double *)malloc(Ncols * Ncols * sizeof(double));
double *h_S = (double *)malloc(min(Nrows, Ncols) * sizeof(double));
// --- device side SVD workspace and matrices
double *d_U; gpuErrchk(cudaMalloc(&d_U, Nrows * Nrows * sizeof(double)));
double *d_V; gpuErrchk(cudaMalloc(&d_V, Ncols * Ncols * sizeof(double)));
double *d_S; gpuErrchk(cudaMalloc(&d_S, min(Nrows, Ncols) * sizeof(double)));
// --- CUDA SVD initialization
cusolveSafeCall(cusolverDnDgesvd_bufferSize(solver_handle, Nrows, Ncols, &work_size));
double *work; gpuErrchk(cudaMalloc(&work, work_size * sizeof(double)));
// --- CUDA SVD execution
cusolveSafeCall(cusolverDnDgesvd(solver_handle, 'A', 'A', Nrows, Ncols, d_A, Nrows, d_S, d_U, Nrows, d_V, Ncols, work, work_size, NULL, devInfo));
int devInfo_h = 0; gpuErrchk(cudaMemcpy(&devInfo_h, devInfo, sizeof(int), cudaMemcpyDeviceToHost));
if (devInfo_h != 0) std::cout << "Unsuccessful SVD execution\n\n";
// --- Moving the results from device to host
gpuErrchk(cudaMemcpy(h_S, d_S, min(Nrows, Ncols) * sizeof(double), cudaMemcpyDeviceToHost));
gpuErrchk(cudaMemcpy(h_U, d_U, Nrows * Nrows * sizeof(double), cudaMemcpyDeviceToHost));
gpuErrchk(cudaMemcpy(h_V, d_V, Ncols * Ncols * sizeof(double), cudaMemcpyDeviceToHost));
std::cout << "Singular values\n";
for(int i = 0; i < min(Nrows, Ncols); i++)
std::cout << "d_S["<<i<<"] = " << std::setprecision(15) << h_S[i] << std::endl;
std::cout << "\nLeft singular vectors - For y = A * x, the columns of U span the space of y\n";
for(int j = 0; j < Nrows; j++) {
printf("\n");
for(int i = 0; i < Nrows; i++)
printf("U[%i,%i]=%f\n",i,j,h_U[j*Nrows + i]);
}
std::cout << "\nRight singular vectors - For y = A * x, the columns of V span the space of x\n";
for(int i = 0; i < Ncols; i++) {
printf("\n");
for(int j = 0; j < Ncols; j++)
printf("V[%i,%i]=%f\n",i,j,h_V[j*Ncols + i]);
}
cusolverDnDestroy(solver_handle);
return 0;
}
Utilities.cuh
#ifndef UTILITIES_CUH
#define UTILITIES_CUH
extern "C" int iDivUp(int, int);
extern "C" void gpuErrchk(cudaError_t);
extern "C" void cusolveSafeCall(cusolverStatus_t);
#endif
012 का उपयोग कर सकते करने के लिए
Utilities.cu
#include <stdio.h>
#include <assert.h>
#include "cuda_runtime.h"
#include <cuda.h>
#include <cusolverDn.h>
/*******************/
/* iDivUp FUNCTION */
/*******************/
extern "C" int iDivUp(int a, int b){ return ((a % b) != 0) ? (a/b + 1) : (a/b); }
/********************/
/* CUDA ERROR CHECK */
/********************/
// --- Credit to http://stackoverflow.com/questions/14038589/what-is-the-canonical-way-to-check-for-errors-using-the-cuda-runtime-api
void gpuAssert(cudaError_t code, char *file, int line, bool abort=true)
{
if (code != cudaSuccess)
{
fprintf(stderr,"GPUassert: %s %s %d\n", cudaGetErrorString(code), file, line);
if (abort) { exit(code); }
}
}
extern "C" void gpuErrchk(cudaError_t ans) { gpuAssert((ans), __FILE__, __LINE__); }
/**************************/
/* CUSOLVE ERROR CHECKING */
/**************************/
static const char *_cudaGetErrorEnum(cusolverStatus_t error)
{
switch (error)
{
case CUSOLVER_STATUS_SUCCESS:
return "CUSOLVER_SUCCESS";
case CUSOLVER_STATUS_NOT_INITIALIZED:
return "CUSOLVER_STATUS_NOT_INITIALIZED";
case CUSOLVER_STATUS_ALLOC_FAILED:
return "CUSOLVER_STATUS_ALLOC_FAILED";
case CUSOLVER_STATUS_INVALID_VALUE:
return "CUSOLVER_STATUS_INVALID_VALUE";
case CUSOLVER_STATUS_ARCH_MISMATCH:
return "CUSOLVER_STATUS_ARCH_MISMATCH";
case CUSOLVER_STATUS_EXECUTION_FAILED:
return "CUSOLVER_STATUS_EXECUTION_FAILED";
case CUSOLVER_STATUS_INTERNAL_ERROR:
return "CUSOLVER_STATUS_INTERNAL_ERROR";
case CUSOLVER_STATUS_MATRIX_TYPE_NOT_SUPPORTED:
return "CUSOLVER_STATUS_MATRIX_TYPE_NOT_SUPPORTED";
}
return "<unknown>";
}
inline void __cusolveSafeCall(cusolverStatus_t err, const char *file, const int line)
{
if(CUSOLVER_STATUS_SUCCESS != err) {
fprintf(stderr, "CUSOLVE error in file '%s', line %d\n %s\nerror %d: %s\nterminating!\n",__FILE__, __LINE__,err, \
_cudaGetErrorEnum(err)); \
cudaDeviceReset(); assert(0); \
}
}
extern "C" void cusolveSafeCall(cusolverStatus_t err) { __cusolveSafeCall(err, __FILE__, __LINE__); }
मैग्मा का उपयोग करके इस दृष्टिकोण बनाम आप क्या सोचते हैं? –
@AndreasYankopolus मैंने दो पुस्तकालयों की तुलना नहीं की है, क्षमा करें। – JackOLantern
- 1. सीयूडीए
- 2. सीयूडीए
- 3. सीयूडीए
- 4. सीयूडीए
- 5. सीयूडीए
- 6. सीयूडीए
- 7. सीयूडीए
- 8. सीयूडीए
- 9. सीयूडीए
- 10. सीयूडीए
- 11. सीयूडीए टेकिट और सीयूडीए एसडीके
- 12. सीयूडीए कर्नेल
- 13. सीयूडीए कर्नेल
- 14. सीयूडीए थ्रस्ट
- 15. सीयूडीए शुरुआती -
- 16. सीयूडीए सरणी
- 17. सीयूडीए समर्थन
- 18. सीयूडीए डिवाइस
- 19. एक्सकोड और सीयूडीए एकीकरण
- 20. सीयूडीए .net के लिए?
- 21. शुरुआती सीयूडीए प्रोग्राम
- 22. मैथमैटिका और सीयूडीए
- 23. सीयूडीए और आरसीपीपी
- 24. सीयूडीए युद्ध और अधिभोग
- 25. सीयूडीए डॉट उत्पाद
- 26. गोलांग कॉलिंग सीयूडीए लाइब्रेरी
- 27. सीयूडीए एक्सपी() एक्सपीएफ() और __expf()
- 28. सीयूडीए प्रोग्रामिंग पर साक्षात्कार प्रश्न?
- 29. सीयूडीए बनाम ओपनसीएल प्रदर्शन तुलना
- 30. सीयूडीए कोर बनाम थ्रेड गिनती
बैच solver/मैट्रिक्स उलटा कोड CUDA पर पोस्ट के अनुरूप डेवलपर वेबसाइट पंजीकृत आप एक मैट्रिक्स-प्रति-धागा या एक मैट्रिक्स-प्रति-धागा ब्लॉक दृष्टिकोण पर विचार कर सकते। यह अच्छा काम करता है यदि बैच आकार बड़ा है और matrices बहुत छोटे हैं। आपके मामले में एन और डी के लिए सामान्य मूल्य क्या हैं? – njuffa
बीएलएएस बैच मोड में केवल मैट्रिक्स गुणा है, है ना? मैं एसवीडी के लिए इसका उपयोग कैसे कर सकता हूं? और क्या आप मुझे जीपीयू में धागे या ब्लॉक को विभाजित करने के तरीके का एक उदाहरण उदाहरण दे सकते हैं और प्रत्येक इकाई समानांतर में एक एसवीडी करता है? उदाहरण के लिए यदि एन = 500 डी = 20। धन्यवाद! –
मैंने अपनी पोस्ट संपादित की है। मुझे आशा है कि यह सहायक होगा। – JackOLantern