Kirjautuminen

Haku

Tehtävät

Keskustelu: Ohjelmointikysymykset: [VB.NET] Intensiivinen prosessi

Sivun loppuun

ErroR++ [18.03.2012 17:51:36]

#

Moi!
Miten toteutetaan intensiivinen prosessi, joka kahmisi itselleen kaiken vapaan suoritinajan? Minulla on nyt ohjelman nopeuttamiseen tälläinen koodi:

For Each arg In Environment.GetCommandLineArgs()
            If arg = "now" Then 'parametrit
                Shell("cmd.exe /c ""START /low files.exe""", AppWinStyle.Hide) 'tuon lowin tilalle voi laittaa vaikka realtime tai high, ja silti tulos on aivan sama
                End 'koeajossa parametrina on "now"
            End If
        Next
        Me.Show() 'nämä
        Application.DoEvents() 'kolme
        Me.Activate() 'riviä, koska koodi on form_loadissa ja lopussa on end
        Process.GetCurrentProcess().PriorityClass = ProcessPriorityClass.RealTime 'prioriteetiksi 24
        System.Threading.Thread.CurrentThread.Priority = Threading.ThreadPriority.Highest 'säikeellekkin kunnollinen prioriteetti
        Process.GetCurrentProcess().PriorityBoostEnabled = True 'boosti

Mutta silti ohjelma käyttää tehoja vain 25%, joka on sama määrä, jolla jotkut toiset minun ohjelmat pyörivät (niissä ei ole edes noita prioriteettihöskiä)!
F-Securen tarkistusprosessikin (fssm32.exe, F-Secure Scanner Manager 32-bit) käyttää suoritinaikaa parhaimmillaan 99%.

Deffi [18.03.2012 18:24:18]

#

Kokeileppa tehdä useampi säie (thread).

ErroR++ [18.03.2012 18:37:18]

#

Niistä minulla on erittäin huonoja kokemuksia...

Ohjelmassa on yksi rekursiota hyödyntävä aliohjelma, joka selaa kaikki hakemistot ja tiedostot läpi ja kutsuu erityistä aliohjelmaa joka etsii tiedoston nimestä jotakin merkkijonoja (virusskannerin runko, paitsi että oikeat skannerit kahlaavat tiedostot läpi). Miten tuon toteuttaisin säikeillä? Jokainen hakemistoko eri säikeeseen?

-tossu- [18.03.2012 18:53:52]

#

Oletko edes varmistanut, että CPU on rajoittava tekijä? Ellet tee tiedostojen nimille todella ihmeellistä tarkistusta, kovalevyn nopeus on varmasti suurin rajoite.

En myöskään halua, että ilmeisesti taustalla pyörivä ohjelma varaa itselleen kaiken prosessoriajan. Prioriteetin nostamisen sijaan voisit laskea sitä.

Mikäli haluat välttämättä ottaa moniytimisestä prosessorista kaiken irti, joudut käyttämään säikeitä, mutta uskon, että tapauksessasi vaikeudet ovat hyötyjä suuremmat.

ErroR++ [18.03.2012 19:18:52]

#

-tossu- kirjoitti:

Oletko edes varmistanut, että CPU on rajoittava tekijä? Ellet tee tiedostojen nimille todella ihmeellistä tarkistusta, kovalevyn nopeus on varmasti suurin rajoite.

En oikein älynnyt, mutta ainakaan kiintolevyn nopeus ei tässä mikään rajoite ole. Kun ajan ohjelmaa ensimmäisellä kerralla viimeisimmästä koneen käynnistyksestä, se etsii kiintolevyltä tiedostoja. Mutta sen jälkeen se lukee ainoastaan C:\$Mft -tiedostoa (tilanvaraustaulukko), kunnes käynnistän koneen uudestaan.

-tossu- kirjoitti:

En myöskään halua, että ilmeisesti taustalla pyörivä ohjelma varaa itselleen kaiken prosessoriajan. Prioriteetin nostamisen sijaan voisit laskea sitä.

Ei se toimi taustalla. Kyseessä on siis eräänlainen tiedostojen etsintäohjelma, joka kurkkii kaikkiin paikkoihin, joihin pääsee (erroreita tulee yleensä 216 tai 419).

Ja ne säikeet tosiaan ovat inhottavia.

ErroR++ [19.03.2012 17:03:02]

#

Yritimpäs vielä niin, että se rekursiolla tomiva aliohjelma tumppaa ne kaikki rekursiot ThreadPooliin. Tulos on tietenkin, että labeli, johon tulokset tulee, päivittyy, mutta ohjelma loppuu ennen aikojaan.

tepokas [19.03.2012 18:31:46]

#

ErroR++ kirjoitti:

Yritimpäs vielä niin, että se rekursiolla tomiva aliohjelma tumppaa ne kaikki rekursiot ThreadPooliin. Tulos on tietenkin, että labeli, johon tulokset tulee, päivittyy, mutta ohjelma loppuu ennen aikojaan.

Pystytkö esittämään sitä formi-loadia ja rekursiota jota koitat ajaa? Vois selventää tilannetta enemmän.

ErroR++ [20.03.2012 07:48:21]

#

No voinhan nekin tänne laittaa, kunhan pääsisin omalle koneelle.

Metabolix [20.03.2012 14:29:04]

#

Ei ole mitään järkeä laittaa jokaista rekursion haaraa omaan säikeeseensä. Ei ole mikään ihme, jos säikeiden maksimimäärä tai muistiraja tulee vastaan.

Sen sijaan voisit laittaa hakemistot pinoon ja käsitellä niitä usealla säikeellä silmukassa. Alussa pitää lisätä pinoon haun ensimmäinen hakemisto. Sitten voit käynnistää haluamasi määrän säikeitä, jotka käyttävät samaa silmukkaa:

Toista:
	Kesken = kyllä.
	Ota pinosta seuraava hakemisto. (TryPop)
	Jos onnistui:
		Lisää alihakemistot pinoon. (Push)
		Tee tälle hakemistolle muut temput.
	Muuten:
		Kesken = ei.
		Toista, kun pino on tyhjä:
			Jos jollain säikeellä on kesken:
				Odota hetki.
			Muuten:
				Lopeta.

Luokka System.Collection.Concurrent.ConcurrentStack toteuttaa monelle säikeelle turvallisen pinon.

ErroR++ [20.03.2012 14:51:29]

#

Tein koodille pieniä optimointeja ja tässä se koodi:

Public Sub Files(path As String)
        Try
            For Each f As FileInfo In New DirectoryInfo(path).GetFiles()
                lblFiles.Text = f.FullName
                Application.DoEvents()
            Next
            If exitLoop Then fw.Close() : End
            For Each dir As DirectoryInfo In New DirectoryInfo(path).GetDirectories()
                lblFiles.Text = dir.FullName
                Files(dir.FullName)
            Next
        Catch ex As Exception
            totalErrors += 1
        End Try
    End Sub

Koodissa on lisäksi pari muuta osaa joita en nyt tänne viitsi laittaa.

Muuten, tänään tuli uusi kiintolevy WinXP-koneeseen. Ubuntua siihen tällä hetkellä asennan.

tepokas [20.03.2012 20:02:23]

#

Nop hankalapa tuosta on sanoa. Tuo Files ei taida kyllä luoda yhtään uutta threadia.
Jos haluat kokeilla threadpool-käyttöä, niin tuossa olisi sellanen rungon aloitelma, jonka päälle voi loput rakentaa.
(Notepadillä rustattu, joten voi sisältää monennäköistä, mutta korjaileppa siitä)

Nop eipä se ihan notepadillä onnistunut, joten poistin sen. Kokeile tätä... ja muokkaa omaan sopivaksi.

Imports System.Threading
Imports System.IO
Imports System.Runtime.InteropServices

Module Module1

    'Sisältää Files taskin parametrit (rakentele setterit ja getterit ja muut puuttuvat)
    Class TaskParam
        Public Sub New(ByVal p As String, ByVal astlbl As sendText)
            path = p
            st = astlbl
        End Sub

        Public path As String 'polku jota tutkitaan
        Public Delegate Sub sendText(ByVal text As String) 'delegaatti labeli tekstin asettamiseksi dialogiin
        Public st As sendText
    End Class

    Sub Files(ByVal tparam As Object)
        Dim param As TaskParam = CType(tparam, TaskParam)

        For Each dir As DirectoryInfo In New DirectoryInfo(param.path).GetDirectories()
            param.st.Invoke(dir.FullName)
            ThreadPool.QueueUserWorkItem(AddressOf Files, New TaskParam(dir.FullName, param.st))
        Next
        For Each f As FileInfo In New DirectoryInfo(param.path).GetFiles()
            param.st.Invoke(f.FullName)
        Next
    End Sub
    'Tee sub main jotenkin näin
    'Pitäs luoda MultiThreadApartment eli monisäikeinen prosessi. (Dialog-projekti ei ole MTA)
    <MTAThread()> _
    Sub Main()
        Dim dialog As New Form1

        'Taskin parametrit
        Dim tp As New TaskParam("C:\\", AddressOf dialog.asetalabeli) 'asettaa delegaatti-function lebeli-tekstin asettamiseksi
        Files(tp) ' aloittaa hakemistojen kahlauksen

        dialog.ShowDialog() ' näyttää dialogin
    End Sub

End Module

'Lisää nämä Formin-koodeihin & tuo TextBox1. Labeliin ei voi tällä kirjoittaa.
Public Class Form1
    Delegate Sub SetTextCallback(ByVal [text] As String)

    Public Sub asetalabeli(ByVal tx As String)
        If Me.TextBox1.InvokeRequired Then
            Dim d As New SetTextCallback(AddressOf asetalabeli)
            Me.BeginInvoke(d, New Object() {[tx]})
        Else
            Me.TextBox1.Text = [tx]
        End If
    End Sub
End Class

ErroR++ [24.03.2012 09:27:10]

#

Jotenkin näin sen arvelin menevän. Kiitos kaikille!

Lisäys: Paitsi että hidastaa hommaa tuhatkertaisesti ja ei päivitä textilaatikkoa...


Sivun alkuun

Vastaus

Aihe on jo aika vanha, joten et voi enää vastata siihen.

Tietoa sivustosta