2012-04-04 40 views
6

Tôi có ứng dụng xem bản đồ cũ bằng WinForms. Đó là sloooooow. (Tốc độ được chấp nhận, nhưng Google Maps, Google Earth xuất hiện và người dùng bị hư hỏng. Bây giờ tôi được phép thực hiện nếu nhanh hơn :)Tắt tải chuyển đổi tọa độ sang GPU

Sau khi thực hiện tất cả các cải thiện tốc độ rõ ràng (caching, thực thi song song, không vẽ những gì không cần phải rút ra, vv), profiler của tôi cho tôi thấy rằng điểm nghẹt thở thực sự là biến đổi tọa độ khi chuyển đổi điểm từ không gian bản đồ sang không gian màn hình. Thông thường một mã chuyển đổi trông như thế này:

public Point MapToScreen(PointF input) 
    { 
     // Note that North is negative! 
     var result = new Point(
      (int)((input.X - this.currentView.X) * this.Scale), 
      (int)((input.Y - this.currentView.Y) * this.Scale)); 
     return result; 
    } 

Việc thực hiện thực sự là phức tạp hơn. Độ cao/longitues được biểu diễn dưới dạng số nguyên. Để tránh mất độ chính xác, chúng được nhân lên 2^20 (~ 1 triệu). Đây là cách phối hợp được biểu diễn.

public struct Position 
{ 
    public const int PrecisionCompensationPower = 20; 
    public const int PrecisionCompensationScale = 1048576; // 2^20 
    public readonly int LatitudeInt; // North is negative! 
    public readonly int LongitudeInt; 
} 

Điều quan trọng là các yếu tố quy mô có thể được ràng buộc rõ ràng với sức mạnh của 2. Điều này cho phép chúng tôi thay thế phép nhân bằng bithift. Vì vậy, các thuật toán thực trông như thế này:

public Point MapToScreen(Position input) 
    { 
     Point result = new Point(); 
     result.X = (input.LongitudeInt - this.UpperLeftPosition.LongitudeInt) >> 
        (Position.PrecisionCompensationPower - this.ZoomLevel); 
     result.Y = (input.LatitudeInt - this.UpperLeftPosition.LatitudeInt) >> 
        (Position.PrecisionCompensationPower - this.ZoomLevel); 
     return result; 
    } 

(UpperLeftPosition representents góc trên bên trái của màn hình trong không gian bản đồ.) Tôi nghĩ hiện nay của việc dỡ tải tính toán này cho GPU. Bất cứ ai có thể chỉ cho tôi một ví dụ làm thế nào để làm điều đó?

Chúng tôi sử dụng .NET4.0, nhưng mã tốt nhất nên chạy trên Windows XP. Hơn nữa, các thư viện thuộc GPL mà chúng tôi không thể sử dụng.

Trả lời

1

Bây giờ một năm sau, vấn đề phát sinh một lần nữa, và chúng tôi tìm thấy một câu trả lời rất nguy hiểm. Tôi cảm thấy một chút ngu ngốc không nhận ra nó trước đó. Chúng tôi rút ra các yếu tố địa lý để bitmap thông qua WinForms GDI bình thường. GDI được tăng tốc phần cứng. Tất cả những gì chúng ta phải làm là KHÔNG làm việc chuyển đổi bởi chính chúng ta nhưng thiết lập các thông số quy mô của đối tượng System.Drawing.Graphics: Graphics.TranslateTransform (...) và Graphics.ScaleTransform (...) Chúng ta không thậm chí cần lừa với sự dịch chuyển bit.

:)

2

tôi đề nghị bạn xem xét sử dụng OpenCL và Cloo để làm điều này - có một cái nhìn tại vector add example và sau đó thay đổi này để lập bản đồ các giá trị bằng cách sử dụng hai ComputeBuffer s (một cho mỗi LatitudeIntLongitudeInt ở mỗi điểm) để 2 đầu ra ComputeBuffer s. Tôi nghi ngờ mã OpenCL sẽ trông giống như sau:

__kernel void CoordTrans(__global int *lat, 
         __global int *lon, 
         __constant int ulpLat, 
         __constant int ulpLon, 
         __constant int zl, 
         __global int *outx, 
         __global int *outy) 
{ 
    int i = get_global_id(0);   
    const int pcp = 20; 

    outx[i] = (lon[i] - ulpLon) >> (pcp - zl); 
    outy[i] = (lat[i] - ulpLat) >> (pcp - zl); 
} 

nhưng bạn sẽ thực hiện nhiều hơn một phép biến đổi trên mỗi lõi. Tôi cần phải vội vàng đi, tôi khuyên bạn nên đọc lên trên opencl trước khi làm điều này.

Ngoài ra, nếu số lượng coords là hợp lý (< 100.000/1.000.000), giải pháp không dựa trên gpu có thể sẽ nhanh hơn.

1

Tôi đến từ nền CUDA và chỉ có thể nói cho NVIDIA GPU, nhưng ở đây sẽ có.

Sự cố khi thực hiện việc này trên GPU là thời gian hoạt động/chuyển của bạn.

Bạn có thứ tự 1 hoạt động để thực hiện cho mỗi phần tử. Bạn thực sự muốn làm nhiều hơn điều này cho mỗi yếu tố để có được một cải thiện tốc độ thực sự. Băng thông giữa bộ nhớ toàn cầu và các luồng trên GPU là khoảng 100GB/s. Vì vậy, nếu bạn phải tải một số nguyên 4 Byte để làm một FLOP, tốc độ tối đa lý thuyết của bạn là 100/4 = 25 FLOPS. Điều này là xa hàng trăm FLOPS được quảng cáo.

Lưu ý đây là lý thuyết tối đa, kết quả thực có thể tồi tệ hơn. Và điều này thậm chí còn tồi tệ hơn nếu bạn đang tải nhiều hơn một phần tử. Trong trường hợp của bạn, nó trông giống như 2, vì vậy bạn có thể nhận được tối đa 12.5 FLOPS từ nó. Trong thực tế, nó gần như chắc chắn sẽ thấp hơn.

Nếu điều này nghe có vẻ ổn với bạn, hãy thực hiện nó!

+0

+1 để hiển thị ranh giới lý thuyết. – user256890

+0

Chỉ cần đặt các con số theo quan điểm, tốc độ gần đúng của CPU 2 lõi trung bình trong FLOP là bao nhiêu? – user256890

+0

Tùy thuộc vào những gì bạn gọi là FLOP. Giả sử CPU 2 lõi của bạn có tốc độ xung nhịp là 2 GHz và FLOP mất 4 chu kỳ đồng hồ. Bạn có thể làm 2 * 2/4 = 1 GFLOP. Đó là một ước tính rất thô sơ. –

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