0

単一のタスクと組み合わせて個別のビットマップに描画するために複数のタスクを使用する場合、どのような理由でパフォーマンスが向上しませんか?(コードを参照)

Private test1 As bitmap_drawer
Private test2 As bitmap_drawer
Private test3 As bitmap_drawer
Private test4 As bitmap_drawer
Private tmptime As String
Private tmptime_1 As DateTime
Private tmptime_2 As DateTime
Private tmptimespan_1 As New TimeSpan


Sub Main()

    Console.WriteLine("4 tasks (parallel) graphics.draw")

    test1 = New bitmap_drawer
    test2 = New bitmap_drawer
    test3 = New bitmap_drawer
    test4 = New bitmap_drawer

    tmptime_1 = DateTime.Now


    Dim action1 As Action(Of Object) = Sub(obj As Object)
                                           Console.WriteLine("Task={0}, Thread={1}", Task.CurrentId, Thread.CurrentThread.ManagedThreadId)
                                           test1.DoDrawing()
                                       End Sub
    Dim action2 As Action(Of Object) = Sub(obj As Object)
                                           Console.WriteLine("Task={0}, Thread={1}", Task.CurrentId, Thread.CurrentThread.ManagedThreadId)
                                           test2.DoDrawing()
                                       End Sub

    Dim action3 As Action(Of Object) = Sub(obj As Object)
                                           Console.WriteLine("Task={0}, Thread={1}", Task.CurrentId, Thread.CurrentThread.ManagedThreadId)
                                           test3.DoDrawing()
                                       End Sub

    Dim action4 As Action(Of Object) = Sub(obj As Object)
                                           Console.WriteLine("Task={0},  Thread={1}", Task.CurrentId, Thread.CurrentThread.ManagedThreadId)
                                           test4.DoDrawing()
                                       End Sub


    Dim t1 As New Task(action1, "1")
    Dim t2 As New Task(action2, "2")
    Dim t3 As New Task(action3, "3")
    Dim t4 As New Task(action4, "4")

    t1.Start()
    t2.Start()
    t3.Start()
    t4.Start()

    Do

    Loop Until t1.IsCompleted And t2.IsCompleted And t3.IsCompleted And t4.IsCompleted

    t1.Dispose()
    t2.Dispose()
    t3.Dispose()
    t4.Dispose()

    tmptime_2 = DateTime.Now
    tmptimespan_1 = (tmptime_2 - tmptime_1)
    tmptime = tmptimespan_1.Seconds.ToString & "sec  " & tmptimespan_1.Milliseconds.ToString & "msec"
    Console.WriteLine("   parallel total: " & tmptime)     ''time:  1sec 136ms


    ''++++++++++++++++++++++++++++++++++++++++++++++++++++++++

    Console.WriteLine("  ")
    Console.WriteLine("4 tasks (serial) graphics.draw")
    tmptime_1 = DateTime.Now

    test1.DoDrawing()
    test2.DoDrawing()
    test3.DoDrawing()
    test4.DoDrawing()


    tmptime_2 = DateTime.Now
    tmptimespan_1 = (tmptime_2 - tmptime_1)
    tmptime = tmptimespan_1.Seconds.ToString & "sec  " & tmptimespan_1.Milliseconds.ToString & "msec"
    Console.WriteLine("   serial total: " & tmptime)   ''time:  0sec 857ms

    ''Conclusion: Both methods generate almost same time

    Console.ReadKey()
End Sub

今クラスbitmapdrawer

Public Class bitmap_drawer

Private tmptime As String
Private tmptime_1 As DateTime
Private tmptime_2 As DateTime
Private tmptimespan_1 As New TimeSpan



Private drawing_parts() As drawing_part


Private g As Graphics
Public bm As Bitmap

Sub New()
    ''init drawing data array
    ReDim drawing_parts(124999)

    ''create drawing data
    MakeDrawingData()

    ''create a bitmap
    bm = New Bitmap(1000, 1000, Imaging.PixelFormat.Format32bppPArgb)
    ''create  graphics from the bitmap
    g = Graphics.FromImage(bm)

End Sub

Sub DoDrawing()
    Dim i As Int32
    tmptime_1 = DateTime.Now
    Dim drawing_pen As New Pen(Color.Black, 0)

    '' do the drawing on the bitmap
    For i = 0 To 124999
        g.DrawPath(drawing_pen, drawing_parts(i).pat)
    Next

    tmptime_2 = DateTime.Now
    tmptimespan_1 = (tmptime_2 - tmptime_1)
    tmptime = tmptimespan_1.Seconds.ToString & "sec  " & tmptimespan_1.Milliseconds.ToString & "msec"
    Console.WriteLine("                   " & tmptime)

End Sub

Private Sub MakeDrawingData()
    Dim x, y As Int32
    Dim i As Int32
    i = 0
    For y = 0 To 249
        For x = 0 To 249
            drawing_parts(i) = New drawing_part With {.pat = New GraphicsPath}
            drawing_parts(i).pat.AddRectangle(New Rectangle(New Point(6 * x, 6 * y), New Size(5, 5)))
            drawing_parts(i).pat.Flatten()
            i += 1
            drawing_parts(i) = New drawing_part With {.pat = New GraphicsPath}
            drawing_parts(i).pat.AddEllipse(6 * x, 6 * y, 8, 5)
            drawing_parts(i).pat.Flatten()
            i += 1
        Next
    Next


End Sub

エンドクラス

今クラスdrawingpart

Public Class drawing_part


Private tmp_pat As GraphicsPath
Public Property pat() As GraphicsPath
    Get
        Return tmp_pat
    End Get
    Set(ByVal Value As GraphicsPath)
        tmp_pat = Value
    End Set
End Property

エンドクラス

4

1 に答える 1

1

GDI operations are hardware accelerated - i.e. it uses the GPU to do as much of the drawing as possible. However the GPU is a single hardware resource, shared by all threads. So even if you have 4 threads running in parallel on a suitable CPU, the GPU will still be doing the work. There will also be overhead involved in switching between multiple tasks.

However if your drawing operation had a lot of CPU usage - calculating exactly what to draw for example - then it might be a win to parallelise it.

于 2012-12-09T09:54:33.963 に答える