Trang 1 trên tổng số 6 123... Cuối cùngCuối cùng
Từ 1 tới 10 trên tổng số 55 kết quả

Đề tài: Kỹ thuật lập trình song song

  1. #1
    Ngày gia nhập
    05 2009
    Nơi ở
    kyoto Japan
    Bài viết
    18

    Mặc định Kỹ thuật lập trình song song

    Chào các bạn. Hầu hết các chương trình của chúng ta đều lập trình cho 1 core. tốc độ thực thi chuơng trình sẽ rất khó nâng cấp. trừ khi chúng ta nâng cấp cấu hình máy.
    Hiện nay các chíp đa lõi đã xuất hiện khá nhiều, nhưng chúng ta vẫn chưa tận dụng được khả năng xử lý đa lõi đó.
    Mình đã làm nhiều đự án "áp dụng trong ngành công nghiệp" ở nhật bản. Các dự án này lúc đầu là ứng dụng xử lý song song đa lõi của chip intel. Đương nhiên tốc độ tăng rất cao, gần gấp đôi so với 1 lõi. Tuy nhiên với tốc độ này thì vẫn chưa thỏa mãn được nhu cầu, nên công ty mình chuyển sang dùng card đồ họa để lập trình song song.
    để thuyết phục những gì mình nói các bạn xem một số kết quả nha.
    dự án này được viết cho công ty Totoku, một công ty chuyên về các thiết bị xử lý ảnh trong y tế. dự án này viết cho hệ thống máy scan chuẩn đoán bệnh ung thư vú của phụ nữ.

    CPU intel core2duo 6600 2.4GHz
    GPU nvidia Geforce 8800GTS

    dữ liệu xử lý là file ảnh bmp 5MB, giá trị sau đây được lấy trung bình từ 100 lần hoạt động.
    cpu 1core: 427.518ms
    cpu 2cores: 215.982ms
    gpu 8800gts: 30.874ms


    các bạn thấy GPU ứng tượng không?
    tiếp sau trang giới thiệu này thì mình xinh trình bày một kỹ thuật lập trình song song, dựa trên nền tảng GPU của NVIDIA. và phần mềm hỗ trợ lập trình đó là CUDA.
    "nếu bài viết này vào ở đây không đúng địa chỉ, xin mod chuyển giúp"

  2. #2
    Ngày gia nhập
    05 2009
    Nơi ở
    kyoto Japan
    Bài viết
    18

    Mặc định So sánh 2 kiến trúc CPU và GPU

    Để dễ hiều, mình xinh được đưa ra so sánh giữa 2 kiến trúc CPU và GPU. hình ảnh sau được lấy từ "cuda programming guide" của nvidia.

    bạn thấy số phần tử xử lý toán học của GPU nhiều hơn hẳn CPU. Điều này mang đến cho GPU một khả năng xử lý song song cực kỳ hiệu quả.
    sau đây là so sánh khả năng xử lý floating-point của GPU và CPU.

    Bắt đầu từ ngày mai, chúng ta sẽ tiếp tục nghiên cứu về cách viết chuơng trình trên card đồ họa nvidia
    yêu cầu hệ thống.
    OS: window hoac linux (mình đang dùng cả 2) tuy nhiên để bước đầu làm quen các bạn nên dùng window
    nếu là window thì cần gói Visual C++ 2005/2008
    Cài CUDA Driver, cuda SDK và cuda toolkit 2.2

    "Mình đã tìm cách chèn hình vào bài viết nhưng không được, bạn nào có thể hướng dẫn giúp không nhỉ"
    Đã được chỉnh sửa lần cuối bởi Quoc Vinh : 17-06-2009 lúc 07:51 PM.

  3. #3
    Ngày gia nhập
    05 2009
    Nơi ở
    kyoto Japan
    Bài viết
    18

    Mặc định chương trình đầu tiên

    để tiện mình hứong dẫn các bước cài đặt
    1. cài bộ visual C++ 2005: Tải 3 chuơng trình Cuda driver, Cuda toolkit, Cuda SDK(nhớ chọn đúng với OS của bạn)
    2. cài Cuda driver
    3. cài Cuda Toolkit
    4. cài Cuda SDK
    sau khi cài xong các bạn chạy thử 1 chuơng trình mẫu của NVIDIA để đảm bảo răng hệ thống của bạn hoạt động được
    bạn vào "C:\Program Files\NVIDIA Corporation\NVIDIA CUDA SDK\bin\win32\Release" chọn chuơng trình "deviceQuery.exe" và chạy thử.
    nếu thành công thì sẽ hiện một console liệt kê các thông số card GPU của bạn, cuối cùng bạn sẽ thấy hiển thị một dòng "Test PASSED".
    nếu không thì các bạn kiểm tra lại các bước trên.

    Viết chuơng trình đầu tiên.
    chuơng trình này sẽ cộng giá trị của 2 mảng. và lưu vào mảng thứ 3
    A = B + C
    đây là một chương trình cực kỳ đơn giản nếu bạn lập trình thông thường. trong trường hợp này bài toán này có rất nhiều điều để học.
    1. tạo 1 project để đơn giản ta tạo một Win32 console application, bạn đặt tên là CUDAAddProgram, nhấn next, nhấn finished.
    2. bạn cần phải chỉ định cho compiler biết thư viện cuda ở đâu và các dll cần dùng
    a. click phải chuột vào project CUDAAddProgram->properties->ConfigurationProperties->C/C++->Genneral, bên phải bạn thấy 1 của sổ. Additional Include Directory. bạn thêm vào dòng sau
    $(CUDA_INC_PATH);./;../../common/inc
    b. click phải chuột vào project CUDAAddProgram->properties->ConfigurationProperties->Linker->Genneral
    bên phải bạn thấy 1 của sổ. Additional Libraries Directory. bạn thêm vào dòng sau
    $(CUDA_LIB_PATH);../../common/lib
    c. click phải chuột vào project CUDAAddProgram->properties->ConfigurationProperties->Linker->Input
    bên phải bạn thấy 1 của sổ. Additional Dependencies. bạn thêm vào 2 thư viện sau
    cudart.lib cutil32.lib
    3. sau khi đã khai báo, tiếp theo bạn thêm 1 file dùng để chứa mã nguồn chuơng trình CUDA
    click phải vào Project CUDAAddProgram->Add->New iterm...->Visual C++->Utility->TextFile, bạn đăt tên là "CudaFunctions.cu" click Add.
    file này có đuôi mở rộng là .cu, chuơng trình dịch CUDA (nvcc) sẽ biên dịch file này.
    click phải vào CudaFunctions.cu->properties->Custom Build step->Command line
    bạn thêm vào dòng sau (dòng lệnh này khai báo cho nvcc biên dịch file này
    "$(CUDA_BIN_PATH)\nvcc.exe" -ccbin "$(VCInstallDir)bin" -c -DWIN32 -D_CONSOLE -D_MBCS -Xcompiler /EHsc,/W3,/nologo,/Wp64,/O2,/Zi,/MT -I"$(CUDA_INC_PATH)" -I./ -I "C:\Program Files\NVIDIA Corporation\NVIDIA CUDA SDK\common\inc" -o $(ConfigurationName)\$(InputName).obj $(InputFileName)
    click phải vào CudaFunctions.cu->properties->Custom Build step->Outputs
    bạn thêm dòng sau
    $(ConfigurationName)\$(InputName).obj
    sau đó nhấn OK
    qua bước này chúng ta đã hoàn tất viẹc khai báo 1 chương trình CUDA

  4. #4
    Ngày gia nhập
    05 2009
    Nơi ở
    kyoto Japan
    Bài viết
    18

    ban đầu chúng ta tạo ra 4 matran đơn giản trên file cpp
    1 matranCPU dùng để chứa dữ liệu tính toán bởi CPU
    1 matranGPU dùng để chứa dữ liệu tính toán bởi GPU
    2 matranB, matranC là 2 matran dùng dể tính toán
    C Code:
    1. #include "stdafx.h"
    2. int *CreateMatrix(size_t width, size_t height, int inValue)
    3. { int *matrix = (int*)malloc(sizeof(int) * widht * height);
    4.   for (size_t i = 0; i < height; i++) {
    5.      for (size_t j = 0; j < width; j++) {
    6.         matrix[i * width + j] = inValue;
    7.       }
    8.     }
    9.    return matrix;
    10. }
    11. void CPUAdd(int *matranA, int *matranB, int *matranC, size_t width, size_t height)
    12. {
    13.   for (size_t i = 0; i < height; i++) {
    14.      for (size_t j = 0; j < width; j++) {
    15.         matrixA[i * width + j] = matrixB[i * width + j] + matrixC[i * width + j];
    16.       }
    17.     }
    18. }
    19. int CheckResult(int *matran1, int *matran2, size_t width, size_t height)
    20. {
    21.   int result = 0;
    22.   for (size_t i = 0; i < height; i++) {
    23.      for (size_t j = 0; j < width; j++) {
    24.        result  = abs(matrix1[i * width + j] - matrix2[i * width + j] );
    25.        if (result  != 0) return result;
    26.       }
    27.     }
    28.     return result;
    29. }
    30. int _tmain(int argc, _TCHAR* argv[])
    31. {
    32.   if (argc >= 2) width = _wtoi(argv[1]);
    33.   else width = 10;
    34.   if (argc >= 3) height = _wtoi(argv[2]);
    35.   else height = 10;
    36.   int *matranCPU = (int*)malloc(sizeof(int) * width * height);
    37.   int *matranGPU = (int*)malloc(sizeof(int) * width * height);
    38.   int *matranB = CreateMatrix(width, height, 9);
    39.   int *matranC = CreateMatrix(width, height, 10);
    40.   CPUAdd(matranCPU, matranB, matranC, width, height);
    41.   cudaSetDevice(0);
    42.   GPUAdd(matranGPU, matranB, matranC, width, height);
    43.   int result = 0;
    44.   result = CheckResult(matranCPU, matranGPU, width, height);
    45.   if (result == 0) printf("Test passed");
    46.   else printf("Test failed");
    47.   free(matranCPU);
    48.   free(matranGPU);
    49.   free(matranB);
    50.   free(matranC);
    51. }

    trong file stdafx.h bạn thêm các đoạn chương trình sau
    C Code:
    1. #pragma once
    2. #define WIN32_LEAN_AND_MEAN    
    3. #include <stdio.h>
    4. #include <tchar.h>
    5. #define XTHREADS 16
    6. #define YTHREADS 16
    7.  
    8. extern "C"
    9. {
    10. void GPUAdd(int* matranA, int *matranB, int *matranC, size_t width, size_t height);
    11. };
    Đã được chỉnh sửa lần cuối bởi lethanh : 17-06-2009 lúc 11:32 PM.

  5. #5
    Ngày gia nhập
    05 2009
    Nơi ở
    kyoto Japan
    Bài viết
    18

    Mặc định viết chương trìn đầu tiên (tt)

    trong file CudaFunctions.cu bạn thêm chuơng trình sau.
    Sau này mình sẽ giải thích cách hoạt động của chuơng trình.
    C Code:
    1. #include "stdafx.h"
    2. __global__ void Kernel(int *matranA, int *matranB, int *matranC, size_t width, size_t height)
    3. {
    4.    int tidX = blockIdx.x * blockDim.x + threadIdx.x;
    5.    int tidY = blockIdx.y * blockDim.y + threadIdx.y;
    6.    if (tidX < width && tidY < height) {
    7.       int index = tidY * width + tidX;
    8.       matranA[index] =  matranB[index] + matranC[index];
    9.    }
    10. }
    11.  
    12. void GPUAdd(int *matranA, int *matranB, int *matranC, size_t width, size_t height)
    13. {
    14.    size_t allocateSize = sizeof(int) * width * height;
    15.    /*tạo vùng nhớ trên ram của GPU để chứa 3 matran A, B, C*/
    16.    int *devMatranA, *devMatranB, *devMatranC;
    17.    cudaMalloc((void**)&devMatranA, allocateSize );
    18.    cudaMalloc((void**)&devMatranB, allocateSize );
    19.    cudaMalloc((void**)&devMatranC, allocateSize );
    20.    /*copy data từ matranB, matranC trên hostRam qua devMatranB, devMatranC trên GPURam*/
    21.    cudaMemcpy(devMatranB, matranB, allocateSize, cudaMemcpyHostToDevice);
    22.    cudaMemcpy(devMatranC, matranC, allocateSize, cudaMemcpyHostToDevice);
    23.    /*tạo số Core (thread) cần thiết để tính toán*/
    24.    dim3 block(XTHREADS, YTHREADS, 1);
    25.    dim3 grid((width + block.x - 1) / block.x, (height + block.y - 1) / block.y, 1);
    26.    /*gọi hàm kernel để tính toán*/
    27.    Kernel<<<grid, block>>>(devMatranA, devMatranB, devMatranC, width, height);
    28.    /*copy data đã tính toán về lại hostRam*/
    29.    cudaMemcpy(matranA, devMatranA, allocateSize, cudaMemcpyDeviceToHost);
    30.   /*giải phóng bộ nhớ của GPU*/
    31.   cudaFree(devMatranA);
    32.   cudaFree(devMatranB);
    33.   cudaFree(devMatranC);
    34. }
    phù phù, thế là xong chuơng trình.
    các bạn build và chạy thử và cho mình biết kết quả nha.
    ngày mai mình sẽ giải thích cách hoạt động của chuơng trình
    Đã được chỉnh sửa lần cuối bởi Quoc Vinh : 17-06-2009 lúc 06:58 PM.

  6. #6
    Ngày gia nhập
    05 2009
    Nơi ở
    kyoto Japan
    Bài viết
    18

    Mặc định giải thích hoạt động của chương trình

    Không biết có bạn nào thử chưa, nhưng không sao. Một ngày nào đó các bạn sẽ cần đến nó. heee
    Bây giờ mình xinh giải thích hoạt động của chương trình.
    Ta có 2 khái niệm cần biết sau.
    1. các hoạt động trên CPU gọi là host
    2. các hoạt động trên GPU gọi là device

    lúc đầu ta tạo các matranGPU, matranB, matranC trên host, các matran này sẽ chiếm một bộ nhớ trên máy tính bạn thông qua hàm malloc() (Ram của máy tính bạn ta gọi là host memory).
    CUDA chỉ tính toán trên bộ nhớ VRam của GPU gọi là device memory (đây là lý do tại sao mình dùng tiêp đầu ngữ "dev" ví dụ devMatranA). Vì vậy ta cần cấp phát vùng nhớ trên deviceMemory thông qua hàm cudaMalloc().
    Tiếp theo ta copy 2 matranA, matranB từ host memory qua device memory devMatranA, devMatranB thông qua hàm cudaMemcpy().
    sau khi copy xong, dữ liệu cần thiết bây giờ nằm trên VRam (device memory).

    ta yêu cầu cudaDriver tạo cho ta số lượng threads bằng số lượng phần tử trên 1 mảng (width * height). vì vậy mỗi thread chỉ làm 1 nhiệm vụ duy nhất là cộng 2 mảng lưu vào 1 mảng devMatranA (cũng trên VRAM). các thread này hoạt động gần như cùng 1 thời điểm (theo nghĩa đen) tùy vào cấu hình của GPU bạn có bao nhiêu Multiprocessor.

    bạn hãy để ý đến hàm Kernel(). đây là hàm tính toán duy nhất. Bạn thấy rằng trên hàm này không còn 2 vòng lặp "for" quen thuộc cũa chuơng trình thông thường. Nó được thay bằng 2 chỉ mục (indexX, indexY) 2 indexer này xác định chính xác thread nào sẽ thực làm phép toán trên phần tử nào của matranA, matranB, matranC.
    bạn cũng để ý rằng cách gọi hàm Kernel() cũng khá đặc biệt thông qua toán tử tên hàm<<<grid, block>>>(tham biến).

    Sau khi tính toán xong, ta copy dữ liệu đã tính toán từ device memory về host memory thông qua hàm cudaMemcpy().

    cuối cùng ta giải phóng vùng nhớ trên device memory thông qua hàm cudaFree().

  7. #7
    Ngày gia nhập
    05 2009
    Nơi ở
    kyoto Japan
    Bài viết
    18

    Bây giờ ta thử kiểm tra tốc độ tính toán giữa CPU và GPU.
    bạn thử nhập vào kích thước lớn dần từ 1 lên đến kích thước tối đa mà Ram và VRam của bạn có thể đáp ứng được.
    chỉnh lại file "stdafx.h"
    C Code:
    1. #pragma once
    2. #define WIN32_LEAN_AND_MEAN    
    3.  
    4. #include <stdio.h>
    5. #include <tchar.h>
    6. #include <windows.h>
    7. #include <time.h>
    8.  
    9. #define XTHREADS 16
    10. #define YTHREADS 16
    11.  
    12. extern "C"
    13. {
    14. void GPUAdd(int* matranA, int *matranB, int *matranC, size_t width, size_t height);
    15. };
    ta chỉnh lại hàm main()
    C Code:
    1. int _tmain(int argc, _TCHAR* argv[])
    2. {
    3.   if (argc >= 2) width = _wtoi(argv[1]);
    4.   else width = 10;
    5.   if (argc >= 3) height = _wtoi(argv[2]);
    6.   else height = 10;
    7.  
    8.   LARGE_INTEGER start, end, frequency;
    9.   ::QueryPerformanceFrequency(&frequency);
    10.   double processingTime;
    11.  
    12.   int *matranCPU = (int*)malloc(sizeof(int) * width * height);
    13.   int *matranGPU = (int*)malloc(sizeof(int) * width * height);
    14.   int *matranB = CreateMatrix(width, height, 9);
    15.   int *matranC = CreateMatrix(width, height, 10);
    16.  
    17.   ::QueryPerformanceCounter(&start);
    18.   CPUAdd(matranCPU, matranB, matranC, width, height);
    19.   ::QueryPerformanceCounter(&end);
    20.   processingTime = (double)(end.QuadPart - start.QuadPart) / frequency.QuadPart * 1000.0f;
    21.   printf("CPU time: %.3f\n", processingTime);
    22.  
    23.   cudaSetDevice(0);
    24.   ::QueryPerformanceCounter(&start);
    25.   GPUAdd(matranGPU, matranB, matranC, width, height);
    26.   ::QueryPerformanceCounter(&end);
    27.   processingTime = (double)(end.QuadPart - start.QuadPart) / frequency.QuadPart * 1000.0f;
    28.   printf("GPU time: %.3f\n", processingTime);
    29.  
    30.   int result = 0;
    31.   result = CheckResult(matranCPU, matranGPU, width, height);
    32.   if (result == 0) printf("Test passed");
    33.   else printf("Test failed");
    34.  
    35.   free(matranCPU);
    36.   free(matranGPU);
    37.   free(matranB);
    38.   free(matranC);
    39. }
    Đã được chỉnh sửa lần cuối bởi Quoc Vinh : 17-06-2009 lúc 07:54 PM.

  8. #8
    Ngày gia nhập
    05 2009
    Nơi ở
    kyoto Japan
    Bài viết
    18

    Mặc định giải thích hoạt động của chương trình (tt)

    tiếp tục nghiên cứu cách hoạt dộng của chuơng trình nào.
    bạn thấy rằng mình yêu cầu Cuda driver tạo cho mình số thread bằng số phần tử trên mỗi matrix
    Thread được phân ra thành từng nhóm nhỏ, mỗi nhóm ta gọi là 1 block
    trong trường hợp này ta yêu cầu 1 block là (XTHREADS x YTHREADS x 1), theo có nghĩa là mỗi block sẽ chứa 16 x 16 x 1 = 256 threads. mỗi block này sẽ xử lý 1 matran vuông nhỏ (16 x 16) trong matran lớn.
    các block này lại được gom lại thành 1 grid.
    vậy grid là tổ hợp các block. còn block là tổ hợp các threads.
    các bạn xem hình sau sẽ rõ.

    vậy làm sao ta xác định chính xác thread nào xử lý phần tử nào.
    trong hàm Kernel. thread trong mỗi block được xác định thông qua chỉ mục threadIdx.x theo phuơng x, và threadIdx.y theo phuơng y.
    tương tự, block trong 1 grid được xác định thông qua chỉ mục blockIdx.xblockIdx.y
    số lượng thread trong môi block được xác định thông qua XTHREAD, YTHREAD mà ta đã khai báo hoặc truy cập theo cách khác blockDim.xblockDim.y

    như vậy ta xác định chỉ số index của thread trong grid thông qua
    int tidX = blockIdx.x * blockDim.x + threadIdx.x;
    int tidY = blockIdx.y * blockDim.y + threadIdx.y;

    vậy xác định chính xác vị trí của 1 phần tử trong matran thật dễ dàng
    int elementIndex = tidY * width + tidX;

    do mỗi block tạo ra 256 threas, và số lượng block trong grid >= 1, nên số lượng threads trong 1 grid sẽ là bội số của 256. điều gì sẽ xảy ra khi bạn cần tính toán matran 31x10;
    Cuda Driver sẽ tạo cho ta 2 block, mỗi block là 256 threads,
    vì vậy thread nào có chỉ số tidX > 30 sẽ không được hoạt dong,
    thread nào có tidY > 9 sẽ không được hoat động, đó là lý do ta đưa ra 1 điều kiện cho thread nào thỏa mãn điều kiện này thì tính toán, nếu không thì không làm gì cả
    if (tidX < width && tidY < height) {
    //
    }

    đến bước này, các bạn thử thay đổi kích thước matran và kích thuoc block, grid dể kiểm nghiêm kết quả ( ví dụ như số thread sinh ra ít hơn số phần tử trong matran, vậy sẽ có một số phần tử không đươc tính toán.....)
    Đã được chỉnh sửa lần cuối bởi Quoc Vinh : 19-06-2009 lúc 09:33 PM.

  9. #9
    Ngày gia nhập
    05 2009
    Nơi ở
    kyoto Japan
    Bài viết
    18

    Mặc định giải thích hoạt động của chương trình (tt)

    vậy ta gọi hàm và yêu cầu CUDA driver cấp phát thread như thế nào.
    các bạn xem đoạn code sau.
    C Code:
    1. /*tạo số Core (thread) cần thiết để tính toán*/
    2.    dim3 block(XTHREADS, YTHREADS, 1);
    3.    dim3 grid((width + block.x - 1) / block.x, (height + block.y - 1) / block.y, 1);
    4.    /*gọi hàm kernel để tính toán*/
    5.    Kernel<<<grid, block>>>(devMatranA, devMatranB, devMatranC, width, height);
    giả sử ta thay đổi kích thước của block như sau
    C Code:
    1. dim3 block(1, 1, 1);
    2. dim3 grid(width, height, 1);
    3. Kernel<<<grid, block>>>(devMatranA, devMatranB, devMatranC, width, height);
    chương trình vẫn chạy đúng. do số tổng số thread sinh ra vẫn đáp ứng nhu cầu. nhưng tốc độ xử lý lại chậm hơn.
    tại sao tốc độ xử lý chậm hơn nhỉ. do bạn chỉ tạo 1 thread/block vì vậy bạn không tận dụng được overlap time trong xử lý. để giải thích rõ vấn đề này sẽ tốn khá nhiều thời gian, hy vong sau này mình sẽ quay lại giải thích vấn đề này (cho đến bước này ta tạm thời không cần hiểu xâu).
    Lưu ý
    Tổng số threads trong 1 block không quá 512;
    dim3 block(XTHREADS, YTHREADS, ZTHREADS); -> XTHREADX * YTHREADS * ZTHREADS <= 512;Tổng số lượng block trong 1 grid phải nhỏ hơn 65535 cho mỗi phuơng.
    dim3 grid(numOfBlockX, numOfBlockY, numOfBlockZ);
    numOfBlockX và numOfBlockY và numOfBLockZ <= 65535


    cho đến bước này các bạn đã biết cách gọi, cấp phát số threads xử lý và thực thi 1 hàm Kernel trong CUDA.
    Phần tiếp theo sẽ được giới thiệu đến các loại memroy trong GPU.

  10. #10
    Ngày gia nhập
    05 2009
    Nơi ở
    kyoto Japan
    Bài viết
    18

    Mặc định Tổ chức bộ nhớ của nvidia-GPU

    Thông thường khi chúng ta lập trình các ngôn ngữ cấp cao thì hầu hết đều không cần quan tâm đến phần cứng nhiều. Tuy nhiên để lập trình và tối ưu tốc độ của một chuơng trình trên CUDA, ta cần phải hiểu rõ cấu trúc bộ nhớ của GPU.
    Các bộ nhớ chính của GPU sẽ được liệt kê dưới đây
    1. Global memory
    2. Local memory
    3. shared memory
    4. texutre cache
    5. const memory
    6. cuda array
    và các thanh ghi registers.
    Mỗi bộ nhớ có các chức năng riêng và cách truy cập riêng.


    nguồn: heim.ifi.uio.no/~knutm/geilo2008/seland.pdf
    Tiếp theo mình xin trình bày cấu trúc, chức năng và cách sử dụng từng loại bộ nhớ.

Các đề tài tương tự

  1. Lập trình C++ Sử dụng OpenMP để song song giải thuật đệ quy tháp Hà Nội
    Gửi bởi tuyen12a trong diễn đàn Thắc mắc lập trình C/C++/C++0x
    Trả lời: 2
    Bài viết cuối: 07-03-2013, 04:54 PM
  2. Một số phương pháp tính tích phân, sử dụng kĩ thuật lập trình song song[Chuyên đề]
    Gửi bởi mp121209 trong diễn đàn Thủ thuật, Tutorials và Mã nguồn
    Trả lời: 2
    Bài viết cuối: 25-04-2011, 02:40 PM
  3. Giải thuật song song | Thảo luận về các giải thuật song song
    Gửi bởi PoPoPoPo trong diễn đàn Thủ thuật, Tutorials CTDL & Giải thuật
    Trả lời: 3
    Bài viết cuối: 05-11-2010, 01:17 AM
  4. Giải thuật song song cho bài toán quy hoạch động và quay lui
    Gửi bởi chuong01 trong diễn đàn Nhập môn lập trình C/C++
    Trả lời: 4
    Bài viết cuối: 25-06-2010, 09:20 PM
  5. Xin tài liệu về Giải thuật song song
    Gửi bởi Caonguyen12G trong diễn đàn Tài liệu, ebooks và công cụ
    Trả lời: 1
    Bài viết cuối: 11-05-2010, 11:15 AM

Quyền hạn của bạn

  • Bạn không thể gửi đề tài mới
  • Bạn không thể gửi bài trả lời
  • Bạn không thể gửi các đính kèm
  • Bạn không thể chỉnh sửa bài viết của bạn