Shared Code
main.cu
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155
#include <cuda_runtime.h> #include <iostream> #include <vector> #include <string> #include <algorithm> #include <chrono> #include <random> #include <iomanip> using namespace std; // ============================================================ // CUDA ERROR CHECK // // بررسی خطاهای CUDA // ============================================================ // // This macro checks every CUDA API call. // // این ماکرو تمام فراخوانیهای API مربوط به CUDA را بررسی میکند. // // If an error occurs, the program prints the CUDA error message // and terminates. // // اگر خطایی رخ دهد، پیام خطای CUDA نمایش داده شده و برنامه متوقف میشود. // ============================================================ #define CUDA_CHECK(call) \ do \ { \ cudaError_t error = call; \ \ if (error != cudaSuccess) \ { \ cerr << "CUDA ERROR: " \ << cudaGetErrorString(error) \ << endl; \ exit(EXIT_FAILURE); \ } \ } while (0) // ============================================================ // NEEDLEMAN-WUNSCH SCORING PARAMETERS // // پارامترهای امتیازدهی الگوریتم Needleman-Wunsch // ============================================================ // // Match = +2 // // تطابق دو کاراکتر = +2 // // Mismatch = -1 // // عدم تطابق دو کاراکتر = -1 // // Gap = -2 // // ایجاد شکاف = -2 // ============================================================ const int MATCH_SCORE = 2; const int MISMATCH_SCORE = -1; const int GAP_PENALTY = -2; // ============================================================ // DNA GENERATOR // // تولیدکننده رشته DNA // ============================================================ // // Generates reproducible DNA sequences. // // رشتههای DNA قابل تکرار تولید میکند. // // Fixed seeds guarantee that the same input sequences // are generated every time. // // استفاده از Seed ثابت باعث میشود در هر اجرا // // دقیقاً همان رشتهها تولید شوند. // ============================================================ string generateDNA( int length, unsigned int seed) { const char bases[] = { 'A', 'C', 'G', 'T' }; mt19937 generator(seed); uniform_int_distribution<int> distribution(0, 3); string sequence; sequence.reserve(length); for (int i = 0; i < length; i++) { sequence += bases[ distribution(generator) ]; } return sequence; } // ============================================================ // CPU NEEDLEMAN-WUNSCH - MEMORY OPTIMIZED // // نسخه CPU الگوریتم Needleman-Wunsch با حافظه بهینه // ============================================================ // // The standard Needleman-Wunsch algorithm normally requires // O(n*m) memory when the complete matrix is stored. // // نسخه معمولی الگوریتم Needleman-Wunsch برای ذخیره کل ماتریس // // به O(n*m) حافظه نیاز دارد. // // For very large sequences this is impossible. // // برای رشتههای بسیار بزرگ این مقدار حافظه عملی نیست. // // Therefore, only two rows are stored. // // بنابراین فقط دو ردیف از ماتریس نگهداری میشود. // // Time Complexity: // O(n*m) // // پیچیدگی زمانی: // // O(n*m) // // Space Complexity: // O(m) // // پیچیدگی حافظه: // // O(m) // ============================================================ int needlemanWunschCPU( const string& seqA, const string& seqB) { int n = static_cast<int>( seqA.length() ); int m = static_cast<int>( seqB.length() ); // -------------------------------------------------------- // Allocate only two rows // // فقط دو ردیف از ماتریس را ایجاد میکنیم // -------------------------------------------------------- vector<int> previousRow( m + 1 ); vector<int> currentRow( m + 1 ); // -------------------------------------------------------- // Initialize first row // // مقداردهی اولیه ردیف اول // -------------------------------------------------------- previousRow[0] = 0; for (int j = 1; j <= m; j++) { previousRow[j] = j * GAP_PENALTY; } // -------------------------------------------------------- // Process all rows // // پردازش تمام ردیفها // -------------------------------------------------------- for (int i = 1; i <= n; i++) { // ---------------------------------------------------- // Initialize first column // // مقداردهی اولین ستون // ---------------------------------------------------- currentRow[0] = i * GAP_PENALTY; // ---------------------------------------------------- // Calculate current row // // محاسبه ردیف فعلی // ---------------------------------------------------- for (int j = 1; j <= m; j++) { int diagonal = previousRow[j - 1]; int up = previousRow[j]; int left = currentRow[j - 1]; // ------------------------------------------------ // Match / Mismatch // // محاسبه امتیاز تطابق یا عدم تطابق // ------------------------------------------------ int diagonalScore; if ( seqA[i - 1] == seqB[j - 1] ) { diagonalScore = diagonal + MATCH_SCORE; } else { diagonalScore = diagonal + MISMATCH_SCORE; } // ------------------------------------------------ // Gap scores // // محاسبه امتیاز Gap // ------------------------------------------------ int upScore = up + GAP_PENALTY; int leftScore = left + GAP_PENALTY; // ------------------------------------------------ // Select maximum score // // انتخاب بیشترین امتیاز // ------------------------------------------------ currentRow[j] = max( diagonalScore, max( upScore, leftScore ) ); } // ---------------------------------------------------- // Swap rows // // جابجایی ردیف فعلی و قبلی // ---------------------------------------------------- swap( previousRow, currentRow ); } // -------------------------------------------------------- // Final alignment score // // امتیاز نهایی Alignment // -------------------------------------------------------- return previousRow[m]; } // ============================================================ // GPU KERNEL // // هسته GPU // ============================================================ // // The algorithm processes one row at a time. // // الگوریتم ردیف به ردیف پردازش میشود. // // Threads process independent cells inside a row whenever // possible. // // Threadها سلولهای مستقل یک ردیف را پردازش میکنند. // // However, because Needleman-Wunsch has dependencies between // neighboring cells, synchronization is required. // // اما به دلیل وابستگی سلولها به همسایههایشان، Synchronization // // مورد نیاز است. // ============================================================ __global__ void needlemanWunschKernel( const char* seqA, const char* seqB, int* previousRow, int* currentRow, int n, int m, int i) { // -------------------------------------------------------- // Calculate global thread ID // // محاسبه شناسه سراسری Thread // -------------------------------------------------------- int j = blockIdx.x * blockDim.x + threadIdx.x + 1; // -------------------------------------------------------- // Ignore threads outside the sequence // // Threadهای خارج از محدوده رشته را نادیده میگیریم // -------------------------------------------------------- if (j > m) { return; } // -------------------------------------------------------- // The first column is handled separately // // ستون اول به صورت جداگانه مقداردهی میشود // -------------------------------------------------------- if (j == 1) { currentRow[0] = i * GAP_PENALTY; } // -------------------------------------------------------- // Calculate diagonal score // // محاسبه امتیاز قطری // -------------------------------------------------------- int diagonalValue = previousRow[j - 1]; int diagonalScore; if ( seqA[i - 1] == seqB[j - 1] ) { diagonalScore = diagonalValue + MATCH_SCORE; } else { diagonalScore = diagonalValue + MISMATCH_SCORE; } // -------------------------------------------------------- // Calculate UP score // // محاسبه امتیاز از بالا // -------------------------------------------------------- int upScore = previousRow[j] + GAP_PENALTY; // -------------------------------------------------------- // Calculate LEFT score // // محاسبه امتیاز از چپ // -------------------------------------------------------- int leftScore = currentRow[j - 1] + GAP_PENALTY; // -------------------------------------------------------- // Select maximum // // انتخاب بیشترین مقدار // -------------------------------------------------------- currentRow[j] = max( diagonalScore, max( upScore, leftScore ) ); } // ============================================================ // MAIN // // تابع اصلی برنامه // ============================================================ int main() { cout << endl; cout << "============================================================\n"; cout << " CUDA Needleman-Wunsch Sequence Alignment\n"; cout << " Large Sequence Version\n"; cout << "============================================================\n\n"; // ======================================================== // GPU INFORMATION // // اطلاعات GPU // ======================================================== int device = 0; cudaDeviceProp gpu; CUDA_CHECK( cudaGetDeviceProperties( &gpu, device ) ); cout << "GPU: " << gpu.name << endl; cout << "Compute Capability: " << gpu.major << "." << gpu.minor << endl; cout << "SM Count: " << gpu.multiProcessorCount << endl; cout << "VRAM: " << fixed << setprecision(2) << (double)gpu.totalGlobalMem / (1024.0 * 1024.0 * 1024.0) << " GB" << endl; cout << endl; // ======================================================== // GENERATE DNA SEQUENCES // // تولید رشتههای DNA // ======================================================== // // Sequence A = 1,000,000 nucleotides // // رشته A شامل یک میلیون نوکلئوتید است. // // Sequence B = 1,200,000 nucleotides // // رشته B شامل یک میلیون و دویست هزار نوکلئوتید است. // ======================================================== const int SEQUENCE_A_LENGTH = 2000; const int SEQUENCE_B_LENGTH = 2400; cout << "Generating DNA sequences..." << endl; auto generationStart = chrono::high_resolution_clock::now(); string sequenceA = generateDNA( SEQUENCE_A_LENGTH, 12345 ); string sequenceB = generateDNA( SEQUENCE_B_LENGTH, 67890 ); auto generationEnd = chrono::high_resolution_clock::now(); double generationTime = chrono::duration<double, milli>( generationEnd - generationStart ).count(); cout << "DNA generation completed." << endl; cout << "Generation Time: " << fixed << setprecision(3) << generationTime << " ms" << endl; cout << endl; // ======================================================== // VALIDATE INPUT // // بررسی طول رشتهها // ======================================================== int n = static_cast<int>( sequenceA.length() ); int m = static_cast<int>( sequenceB.length() ); cout << "Sequence A length: " << n << endl; cout << "Sequence B length: " << m << endl; cout << endl; if (n != SEQUENCE_A_LENGTH) { cerr << "ERROR: Sequence A length is invalid." << endl; return 1; } if (m != SEQUENCE_B_LENGTH) { cerr << "ERROR: Sequence B length is invalid." << endl; return 1; } // ======================================================== // THEORETICAL FULL MATRIX SIZE // // اندازه تئوری ماتریس کامل // ======================================================== // // A full matrix would contain: // // (n + 1) * (m + 1) // // cells. // // // ماتریس کامل دارای این تعداد سلول خواهد بود: // // (n + 1) * (m + 1) // // We DO NOT allocate this matrix. // // این ماتریس را ایجاد نمیکنیم. // ======================================================== unsigned long long fullMatrixCells = static_cast<unsigned long long>(n + 1) * static_cast<unsigned long long>(m + 1); double theoreticalMemoryGB = ( static_cast<double>( fullMatrixCells ) * sizeof(int) ) / ( 1024.0 * 1024.0 * 1024.0 * 1024.0 ); cout << "============================================================\n"; cout << " MATRIX INFORMATION\n"; cout << "============================================================\n"; cout << "Full Matrix Size: " << n + 1 << " x " << m + 1 << endl; cout << "Full Matrix Cells: " << fullMatrixCells << endl; cout << "Theoretical Full Matrix Memory: " << fixed << setprecision(3) << theoreticalMemoryGB << " TiB" << endl; cout << endl; cout << "IMPORTANT:\n"; cout << "The full matrix is NOT allocated.\n"; cout << "Only two rows are stored.\n"; cout << endl; // ======================================================== // CPU EXECUTION // // اجرای الگوریتم روی CPU // ======================================================== cout << "============================================================\n"; cout << " CPU EXECUTION\n"; cout << "============================================================\n"; auto cpuStart = chrono::high_resolution_clock::now(); int cpuFinalScore = needlemanWunschCPU( sequenceA, sequenceB ); auto cpuEnd = chrono::high_resolution_clock::now(); double cpuTime = chrono::duration<double, milli>( cpuEnd - cpuStart ).count(); cout << "CPU Final Score: " << cpuFinalScore << endl; cout << "CPU Time: " << fixed << setprecision(3) << cpuTime << " ms" << endl; cout << endl; // ======================================================== // GPU MEMORY ALLOCATION // // تخصیص حافظه GPU // ======================================================== char* d_seqA = nullptr; char* d_seqB = nullptr; int* d_previousRow = nullptr; int* d_currentRow = nullptr; // -------------------------------------------------------- // Allocate DNA sequence A // // تخصیص حافظه برای رشته A // -------------------------------------------------------- CUDA_CHECK( cudaMalloc( &d_seqA, n * sizeof(char) ) ); // -------------------------------------------------------- // Allocate DNA sequence B // // تخصیص حافظه برای رشته B // -------------------------------------------------------- CUDA_CHECK( cudaMalloc( &d_seqB, m * sizeof(char) ) ); // -------------------------------------------------------- // Allocate two DP rows // // تخصیص دو ردیف ماتریس Dynamic Programming // -------------------------------------------------------- CUDA_CHECK( cudaMalloc( &d_previousRow, (m + 1) * sizeof(int) ) ); CUDA_CHECK( cudaMalloc( &d_currentRow, (m + 1) * sizeof(int) ) ); // ======================================================== // COPY DNA DATA CPU -> GPU // // انتقال DNA از CPU به GPU // ======================================================== CUDA_CHECK( cudaMemcpy( d_seqA, sequenceA.data(), n * sizeof(char), cudaMemcpyHostToDevice ) ); CUDA_CHECK( cudaMemcpy( d_seqB, sequenceB.data(), m * sizeof(char), cudaMemcpyHostToDevice ) ); // ======================================================== // INITIALIZE FIRST ROW // // مقداردهی ردیف اول // ======================================================== vector<int> firstRow( m + 1 ); firstRow[0] = 0; for (int j = 1; j <= m; j++) { firstRow[j] = j * GAP_PENALTY; } CUDA_CHECK( cudaMemcpy( d_previousRow, firstRow.data(), (m + 1) * sizeof(int), cudaMemcpyHostToDevice ) ); // ======================================================== // GPU EXECUTION // // اجرای الگوریتم روی GPU // ======================================================== cout << "============================================================\n"; cout << " GPU EXECUTION\n"; cout << "============================================================\n"; const int THREADS_PER_BLOCK = 256; int blocks = ( m + THREADS_PER_BLOCK - 1 ) / THREADS_PER_BLOCK; cout << "Threads per Block: " << THREADS_PER_BLOCK << endl; cout << "Blocks per Row: " << blocks << endl; cout << endl; auto gpuStart = chrono::high_resolution_clock::now(); // ======================================================== // PROCESS ROWS // // پردازش ردیفهای ماتریس // ======================================================== for (int i = 1; i <= n; i++) { needlemanWunschKernel<<< blocks, THREADS_PER_BLOCK >>>( d_seqA, d_seqB, d_previousRow, d_currentRow, n, m, i ); CUDA_CHECK( cudaGetLastError() ); // ---------------------------------------------------- // Synchronize before processing the next row // // قبل از پردازش ردیف بعدی Synchronization انجام میشود // ---------------------------------------------------- CUDA_CHECK( cudaDeviceSynchronize() ); // ---------------------------------------------------- // Swap previous and current rows // // جابجایی ردیف قبلی و ردیف فعلی // ---------------------------------------------------- swap( d_previousRow, d_currentRow ); } auto gpuEnd = chrono::high_resolution_clock::now(); double gpuTime = chrono::duration<double, milli>( gpuEnd - gpuStart ).count(); // ======================================================== // COPY FINAL ROW GPU -> CPU // // انتقال ردیف نهایی از GPU به CPU // ======================================================== vector<int> finalRow( m + 1 ); CUDA_CHECK( cudaMemcpy( finalRow.data(), d_previousRow, (m + 1) * sizeof(int), cudaMemcpyDeviceToHost ) ); // ======================================================== // GPU FINAL SCORE // // امتیاز نهایی GPU // ======================================================== int gpuFinalScore = finalRow[m]; // ======================================================== // VERIFY RESULTS // // بررسی صحت نتایج // ======================================================== bool verificationPassed = ( cpuFinalScore == gpuFinalScore ); // ======================================================== // SPEEDUP // // محاسبه Speedup // ======================================================== double speedup = cpuTime / gpuTime; // ======================================================== // FINAL RESULTS // // نتایج نهایی // ======================================================== cout << endl; cout << "============================================================\n"; cout << " FINAL RESULTS\n"; cout << "============================================================\n"; cout << "Sequence A Length : " << n << endl; cout << "Sequence B Length : " << m << endl; cout << endl; cout << "Scoring Parameters\n"; cout << "Match : " << MATCH_SCORE << endl; cout << "Mismatch : " << MISMATCH_SCORE << endl; cout << "Gap : " << GAP_PENALTY << endl; cout << endl; cout << "CPU Final Score : " << cpuFinalScore << endl; cout << "GPU Final Score : " << gpuFinalScore << endl; cout << endl; cout << "CPU Time : " << fixed << setprecision(3) << cpuTime << " ms" << endl; cout << "GPU Time : " << fixed << setprecision(3) << gpuTime << " ms" << endl; cout << "Speedup : " << fixed << setprecision(3) << speedup << "x" << endl; cout << endl; cout << "Result Verification: "; if (verificationPassed) { cout << "PASSED"; } else { cout << "FAILED"; } cout << endl; cout << "============================================================\n"; // ======================================================== // MEMORY INFORMATION // // اطلاعات حافظه // ======================================================== double rowMemoryMB = ( static_cast<double>( (m + 1) * sizeof(int) ) ) / ( 1024.0 * 1024.0 ); cout << endl; cout << "GPU DP Row Memory: " << fixed << setprecision(3) << rowMemoryMB << " MB per row" << endl; cout << "Full Matrix Memory Avoided: " << fixed << setprecision(3) << theoreticalMemoryGB << " TiB" << endl; // ======================================================== // FREE GPU MEMORY // // آزاد کردن حافظه GPU // ======================================================== CUDA_CHECK( cudaFree(d_seqA) ); CUDA_CHECK( cudaFree(d_seqB) ); CUDA_CHECK( cudaFree(d_previousRow) ); CUDA_CHECK( cudaFree(d_currentRow) ); // ======================================================== // RESET CUDA DEVICE // // بازنشانی دستگاه CUDA // ======================================================== CUDA_CHECK( cudaDeviceReset() ); return 0; }
Comments (0)
to post comments and vote
No comments yet. Be the first to share your thoughts!