2010-04-12 34 views
11

Khi tôi hoàn thành việc viết mã cho dự án của mình cho một lớp lập trình đa lõi, tôi đã nghĩ ra điều gì đó thực sự kỳ lạ mà tôi muốn thảo luận với bạn.Nhân OpenCL của tôi chậm hơn trên phần cứng nhanh hơn .. Nhưng tại sao?

Chúng tôi đã được yêu cầu tạo bất kỳ chương trình nào có thể cải thiện đáng kể khi được lập trình cho nền tảng đa lõi. Tôi đã quyết định thử và mã hóa thứ gì đó trên GPU để dùng thử OpenCL. Tôi đã chọn vấn đề chuyển đổi ma trận vì tôi khá quen thuộc với nó (tôi đã song song nó trước đó với open_mpi với tốc độ tuyệt vời cho hình ảnh lớn).

Vì vậy, ở đây là, tôi chọn một tệp GIF lớn (2,5 MB) [2816X2112] và tôi chạy phiên bản tuần tự (mã gốc) và tôi nhận được trung bình 15,3 giây.

Tôi sau đó chạy phiên bản OpenCL mới tôi vừa viết trên MBP tích hợp của tôi GeForce 9400M và tôi nhận được thời gian trung bình 1.26s .. Cho đến nay rất tốt, đó là một tốc độ 12X !!

Nhưng bây giờ tôi vào bảng tiết kiệm năng lượng để bật “Chế độ hiệu suất đồ họa” Chế độ đó tắt GeForce 9400M và bật hệ thống Geforce 9600M GT của tôi. Apple cho biết thẻ này nhanh hơn gấp hai lần so với thẻ tích hợp.

Đoán những gì, thời gian của tôi bằng cách sử dụng card đồ họa kick-ass là 3,2 giây ở mức trung bình ... My 9600M GT có vẻ là chậm hơn so với 9400M hơn hai lần ..

Đối với những người bạn mà là OpenCL nghiêng , Tôi sao chép tất cả dữ liệu vào bộ đệm từ xa trước khi bắt đầu, do đó, tính toán thực tế không yêu cầu khứ hồi tới ram chính. Ngoài ra, tôi cho phép OpenCL xác định phương pháp tối ưu hóa địa phương tối ưu vì tôi đã đọc rằng họ đã thực hiện triển khai khá tốt khi tìm ra thông số đó ..

Có ai có đầu mối không?

chỉnh sửa: mã nguồn đầy đủ với makefiles đây http://www.mathieusavard.info/convolution.zip

cd gimage 
make 
cd ../clconvolute 
make 
put a large input.gif in clconvolute and run it to see results 
+0

Bạn có khởi động lại máy tính sau khi chuyển đổi cạc đồ họa không? AFAIK này là bắt buộc đối với các máy tính này. –

+0

Tôi đã đăng xuất .. khi bạn muốn thay đổi card đồ họa, nó buộc bạn phải đăng xuất và đăng nhập + đầu ra chương trình của tôi tên của card đồ họa hiện đang được sử dụng để tôi có thể đảm bảo nó đang chạy .. – matdumsa

+0

đã thử khởi động lại .. cũng đã cố gắng tăng kích thước vấn đề bằng cách sử dụng hình ảnh 3264x2448 với mặt nạ 12X12 chỉ để tìm kết quả tương tự ... – matdumsa

Trả lời

1

Tôi chạy vào cùng một vấn đề khi tôi đã được thử nghiệm ra OpenCL trên MacBook của tôi. Tôi tin rằng đó là bởi vì GeForce 9400M có tốc độ bus cao hơn đến ngân hàng bộ nhớ chính hơn Geforce 9600M GT. Vì vậy, mặc dù Geforce 9600M GT có nhiều quyền lực hơn so với GeForce 9400M thời gian cần thiết để sao chép bộ nhớ vào GPU quá lâu để thấy được lợi ích của GPU mạnh mẽ hơn trong hoàn cảnh của bạn. Nó cũng có thể do kích thước nhóm công nhân không phù hợp gây ra.

Ngoài ra tôi thấy trang web này rất hữu ích trong trải nghiệm OpenCL của tôi.

http://www.macresearch.org/opencl

+0

Cảm ơn Kendall, nhưng điều macresearch.org là nội dung tôi dựa trên mã thực sự: P Kích thước nhóm công nhân sẽ tự động được thiết lập bằng cách truyền tham số null. – matdumsa

+1

Thử sử dụng các kích thước khác nhau. Mặc định không phải lúc nào cũng tốt nhất. –

+0

ok vì vậy tôi đã thử kích thước khác nhau .. kích thước tự động phát hiện là 16 trên cả hai thẻ .. Tôi có thể nhận được lên đến 17 nhưng nó làm giảm perf trên cả hai thẻ .. Tôi nhận được một lỗi trên 17. Lạ, lạ, lạ ... – matdumsa

1

Việc thực hiện không phải là sự khác biệt duy nhất giữa một 9400M GeForce và Geforce 9600M GT. Hình ảnh lớn nhất là một là GPU rời nhau. Với điều này đến một loạt các khác biệt, trong số đó sau đây có thể có tác động:

  • xu hướng của trình điều khiển cho hàng loạt nhiều lệnh
  • bộ nhớ không đồng đều. GPU thường chỉ truy cập vào bộ nhớ của riêng nó và trình điều khiển di chuyển bộ nhớ qua lại trên bus PCI-E.

Tôi chắc rằng tôi đang thiếu một số ...

Dưới đây là một loạt các ý tưởng mà bạn có thể thử:

  • tránh gọi clFinish. Cách bạn gọi nó giữa tải bộ nhớ và thực thi buộc trình điều khiển làm nhiều việc hơn mức cần thiết. Nó thu thập GPU.
  • cấu hình mã của bạn để xem những gì đang dành thời gian. Tôi không nhận thức được hỗ trợ cho phân tích hiệu suất CL, nhưng với các cuộc gọi clFinish của bạn, nó cung cấp cho bạn ước tính thứ tự đơn giản bằng cách đo lường phía CPU. Lưu ý rằng khó có thể phân biệt điều gì là do độ trễ và điều gì là do thông lượng.
+0

Cảm ơn Bahbar, tôi đã thử xóa cl_finish gợi ý nhưng không thành công .. Sau đó, tôi đã cố gắng xóa tất cả (ngay cả khi không an toàn) và tôi vẫn nhận được cùng một thời gian chạy ... Điều thú vị là OpenCL runtimes mất gấp đôi dài (cả GeForce) nếu tôi rút dây nguồn của máy tính và để pin chạy trên pin. – matdumsa

2

Tôi nhận được kết quả tương tự và tôi không chắc chắn lý do. Hạt nhân của tôi liên quan đến việc sao chép rất ít đến/từ (tôi dự tất cả các dữ liệu cần thiết cho tất cả các cuộc gọi hạt nhân, và chỉ trả về một hình ảnh 512x512). Đó là một raytracer, do đó, hạt nhân làm việc lớn hơn nhiều so với bản sao trở lại (400 + ms đến 10ms). Tuy nhiên, 9600M GT là khoảng 1,5x-2x chậm hơn.

Theo danh sách của nVidia, 9600M GT sẽ có 32 SP (gấp đôi số lượng 9400M). Nó có lẽ là đồng hồ cao hơn quá.

9600M GT có vẻ nhanh hơn trong một số trường hợp, ví dụ: Trò chơi. Xem những liên kết này: http://www.videocardbenchmark.net/video_lookup.php?cpu=GeForce+9600M+GT http://www.videocardbenchmark.net/video_lookup.php?cpu=GeForce+9600M+GT

Theo ars technica:

Bên cạnh đó, một miếng ngon thú vị về thực hiện Snow Leopard được tiết lộ bởi các xét nghiệm sớm. Mặc dù Snow Leopard dường như không cho phép GPU kép hoặc chuyển đổi GPU trực tiếp cho các máy sử dụng chipset NVIDIA GeForce 9400M - một hạn chế được chuyển từ Leopard — nhưng dường như hệ điều hành có thể sử dụng cả hai tài nguyên OpenCL cùng một lúc. Vì vậy, ngay cả khi bạn đã kích hoạt 9600M GT trên MacBook Pro, nếu mã OpenCL gặp phải trong một ứng dụng, Snow Leopard có thể gửi mã đó được xử lý bởi 16 lõi GPU đang ngồi khá nhiều không hoạt động trong 9400M. Tuy nhiên, điều ngược lại là không đúng - khi chạy MacBook Pro chỉ với 9400M, 9600M GT bị tắt hoàn toàn để tiết kiệm điện và không thể sử dụng làm tài nguyên OpenCL.

Điều này có vẻ trái ngược với những gì chúng ta đang thấy. Ngoài ra, tôi chỉ thiết lập rõ ràng ngữ cảnh CL trên một thiết bị tại một thời điểm.

Có một số gợi ý trong số ars forums rằng 9600M GT không hỗ trợ tăng gấp đôi, điều này sẽ giải thích vấn đề này. Tôi có thể cố gắng viết một điểm chuẩn tổng hợp để kiểm tra giả thuyết này.

10

9400M được tích hợp với bộ điều khiển bộ nhớ của bạn trong khi 9600M GT là một thẻ rời rạc được kết nối với bộ điều khiển bộ nhớ của bạn qua bus PCI-e. Điều này có nghĩa rằng khi bạn chuyển bộ nhớ đến 9400M nó chỉ phân bổ nó vào RAM hệ thống. Mặt khác, 9600M gửi dữ liệu qua PCI-e đến bộ nhớ đồ họa chuyên dụng trên thẻ. Chuyển khoản này là điều làm cho điểm chuẩn của bạn dường như chậm hơn.

Nếu bạn muốn so sánh hiệu suất của hai card đồ họa, bạn nên sử dụng chức năng lược tả OpenCL thay vì chức năng đồng hồ bạn đang sử dụng.

cl_int clGetEventProfilingInfo (cl_event event, cl_profiling_info param_name, size_t param_value_size, void *param_value, size_t *param_value_size_ret)

Vượt qua chức năng sự kiện được tạo ra khi bạn đang enqueueing hạt nhân và vượt qua nó CL_PROFILING_COMMAND_START cho đối số thứ hai để có được những điểm khởi đầu của Kernel trong nano giây và CL_PROFILING_COMMAND_END để có được điểm kết thúc của hạt nhân. Hãy chắc chắn sử dụng lệnh này SAU KHI thực hiện hạt nhân đã hoàn thành (các sự kiện giữ giá trị của chúng cho đến khi chúng đi ra khỏi phạm vi.) Bạn cũng có thể lấy thời gian cần để truyền dữ liệu đến thiết bị bằng cách áp dụng chức năng này cho các sự kiện từ enqueueing của bộ đệm. Dưới đây là ví dụ:

 TRACE("Invoking the Kernel") 
    cl::vector<cl::Event> matMultiplyEvent; 
    cl::NDRange gIndex(32,64); 
    cl::NDRange lIndex(16,16); 

    err = queueList["GPU"]->enqueueNDRangeKernel(
               matrixMultiplicationKernel, 
               NULL, 
               gIndex, 
               lIndex, 
               &bufferEvent, 
               matMultiplyEvent); 
    checkErr(err, "Invoke Kernel"); 


    TRACE("Reading device data into array"); 
    err = queueList["GPU"]->enqueueReadBuffer(thirdBuff, 
               CL_TRUE, 
               0, 
               (matSize)*sizeof(float), 
               testC, 
               &matMultiplyEvent, 
               bufferEvent); 
    checkErr(err, "Read Buffer"); 
    matMultiplyEvent[0].wait(); 
    for (int i = 0; i < matSize; i++) { 
     if (i%64 == 0) { 
      std::cout << "\n"; 
     } 
     std::cout << testC[i] << "\t"; 
    } 
    long transferBackStart = bufferEvent[0].getProfilingInfo<CL_PROFILING_COMMAND_START>(); 
    long transferBackEnd = bufferEvent[0].getProfilingInfo<CL_PROFILING_COMMAND_END>(); 
    double transferBackSeconds = 1.0e-9 * (double)(transferBackEnd- transferBackStart); 

    long matrixStart = matMultiplyEvent[0].getProfilingInfo<CL_PROFILING_COMMAND_START>(); 
    long matrixEnd = matMultiplyEvent[0].getProfilingInfo<CL_PROFILING_COMMAND_END>(); 
    double dSeconds = 1.0e-9 * (double)(matrixEnd - matrixStart); 

Ví dụ này sử dụng trình bao bọc C++ nhưng khái niệm phải giống nhau.

Hy vọng điều này sẽ hữu ích.

+0

Cảm ơn, tôi sẽ sớm kiểm tra những gì bạn đề xuất để xem liệu điều đó có giải thích rằng: P – matdumsa

0

Tôi mới sử dụng OpenCL, vì vậy tôi có thể hơi ngây thơ, nhưng tôi nghi ngờ bạn cần phải đi vào bảng tiết kiệm năng lượng để chuyển đổi thiết bị tính toán OpenCL. Tôi tin rằng bạn chọn thiết bị khi thiết lập ngữ cảnh OpenCL trong mã của bạn.

Giả thuyết của tôi: 1) Khi bạn chạy mã của mình mà không vô hiệu hóa GPU tích hợp trước, OpenCL sẽ chọn GPU rời của bạn làm thiết bị tính toán. Mã của bạn chạy trên GPU rời (nhanh). 2) Khi bạn vô hiệu hóa GPU tích hợp trước, bạn buộc tải chạy OS X GUI vào thẻ rời rạc của bạn. Khi bạn chạy mã của mình, nó chạy trên GPU rời rạc, nhưng nó tương thích với GUI của bạn cho các tài nguyên.

Câu trả lời này là 11 tháng sau khi câu hỏi được hỏi, nhưng hy vọng nó sẽ hữu ích cho ai đó ...

Các vấn đề liên quan