我有一个整数列表,其中包含在一组批次中发生特定数字组合的次数,其中每次迭代中出现1到80个20个数字。
让我们说LotCount = 1并且我们正在计算nChoose2组合。 整数计数列表将为80Choose2 = 3,160,每个组合最少出现0次,最多为1次(因为LotCount = 1)。在这个例子中,我们恰好有20Choose2 = 190 1&s;其余为0,但是对于LotCount = 2或更多,它最多为20Choose2 * LotCount和min 20Choose2。
这很容易失控,因为即使LotCount仍然是1,当探测大于" 2"组合,其数量呈指数增长。 20选择3 = 82,160 - 20选择4 = 1,581,580等等
我想要做的是同时并以多线程方式计算出现次数,以便所有CPU内核都能正常工作,因为这是一项非常耗时的任务。
我试图这样做搜索谷歌和东西,但我想我只有"并发"因为应用程序在我的8线程计算机上的CPU使用率高达13%
这是我的原始代码:
Dim DBNumFrom As New List(Of Integer)
Dim DBNumTo As New List(Of Integer)
Dim k As Integer = CInt(nudFindNGrams.Value)
Dim KinoCombinations As New List(Of List(Of Integer))
Dim KinoCombinationsFrequencyIndexes As New List(Of clsNGram)
KinoCombinations = nChooseK(KinoNumbers, k)
...............................
Await Task.Run(
Sub()
For i = 0 To KinoCombinations.Count - 1
KinoCombinationsFrequencyIndexes.Add(New clsNGram With {.nGramCombination = KinoCombinations(i), .Occurrences = 0})
For l = 0 To DBNumFrom.Count - 1
For j = DBNumFrom(l) To DBNumTo(l) Step -1
Dim CombinationIsContainedInCurrentLot As Boolean = True
For f As Integer = 0 To k - 1
If Not KinoGames.Item(j).NumbersArray.Contains(KinoCombinations(i)(f)) Then
CombinationIsContainedInCurrentLot = False
Exit For
End If
Next
If CombinationIsContainedInCurrentLot Then KinoCombinationsFrequencyIndexes(i).Occurrences += 1
Next
Next
Next
End Sub)
经过一番阅读后,我将其改为:
[稍后我称之为并发的函数]
Private Async Function CalcKinoCombinations(ByVal FromIndex As Integer, ByVal ToIndex As Integer, ByVal k As Integer, ByVal KinoCombinations As List(Of List(Of Integer)), DBNumFrom As List(Of Integer), DBNumto As List(Of Integer)) As Task(Of List(Of clsNGram))
Dim KinoCombinationsFrequencyIndexes As New List(Of clsNGram)
Dim Counter As Integer = -1
For i = FromIndex To ToIndex
Counter += 1
KinoCombinationsFrequencyIndexes.Add(New clsNGram With {.nGramCombination = KinoCombinations(i), .Occurrences = 0})
For l = 0 To DBNumFrom.Count - 1
For j = DBNumFrom(l) To DBNumto(l) Step -1
Dim CombinationIsContainedInCurrentLot As Boolean = True
For f As Integer = 0 To k - 1
If Not KinoGames.Item(j).NumbersArray.Contains(KinoCombinations(i)(f)) Then
CombinationIsContainedInCurrentLot = False
Exit For
End If
Next
If CombinationIsContainedInCurrentLot Then KinoCombinationsFrequencyIndexes(Counter).Occurrences += 1
Next
Next
Next
Return KinoCombinationsFrequencyIndexes
End Function
[按钮子内的代码]
Dim CountSwarmsTasksQuery As New List(Of Task(Of List(Of clsNGram)))
If KinoCombinations.Count > CoresCount Then
Dim intCombinationsPerIteration As Integer = CInt(Math.Floor(KinoCombinations.Count / CoresCount))
For i As Integer = 1 To CoresCount
If i = 1 Then
CountSwarmsTasksQuery.Add(CalcKinoCombinations(0, intCombinationsPerIteration, k, KinoCombinations, DBNumFrom, DBNumTo))
ElseIf i < CoresCount Then
CountSwarmsTasksQuery.Add(CalcKinoCombinations((intCombinationsPerIteration * i) - intCombinationsPerIteration + 1, intCombinationsPerIteration * i, k, KinoCombinations, DBNumFrom, DBNumTo))
Else
CountSwarmsTasksQuery.Add(CalcKinoCombinations((intCombinationsPerIteration * i) - intCombinationsPerIteration + 1, KinoCombinations.Count - 1, k, KinoCombinations, DBNumFrom, DBNumTo))
End If
Next
Else
CountSwarmsTasksQuery.Add(CalcKinoCombinations(0, KinoCombinations.Count - 1, k, KinoCombinations, DBNumFrom, DBNumTo))
End If
Dim CountSwarmsTasks As Task(Of List(Of clsNGram))() = CountSwarmsTasksQuery.ToArray
Dim CountSwarmsLstClsNGram() As List(Of clsNGram) = Await Task.WhenAll(CountSwarmsTasks)
For Each item In CountSwarmsLstClsNGram
KinoCombinationsFrequencyIndexes.AddRange(item)
Next
但正如我所说,从我收集的内容中,并发性存在,但这一切都发生在1个线程中,因为这是一个需要cpu的任务,我从中得不到任何好处。我需要并发和每个任务都在一个单独的线程上。
[信息]
我所做的基本上是取nChoosek计数列表并将其除以8(CoreCount变量在我的计算机上返回8)。 订单确实发挥了作用,我喜欢&#34;。当所有&#34;将按照我称之为的顺序返回
如何将8个任务中的每个任务放入不同的线程,然后按照我调用的顺序获取函数结果(List(Of clsNGram)))?
我真的很感谢帮助 - 谢谢你们
答案 0 :(得分:0)
事实证明,我自己想通了,我想我会发布它,以防其他人想要完成相同的任务(将任务划分为多个以并发和多线程方式运行的子任务) )
Public Structure MyStructure
Dim DateAndTime As Date
Dim Numbers() As Integer
Public Overrides Function ToString() As String
Return DateAndTime.ToString("dd/MM/yyyy HH:mm") & " " & Numbers(0).ToString & " " & Numbers(1).ToString & " " & Numbers(2).ToString
End Function
End Structure
Public Class Form1
Dim MyDesign As New List(Of MyStructure)
Dim strMyDesign As New List(Of String)
Public Async Function LoadMyDesign(ByVal FromLineIndex As Integer, ByVal ToLineIndex As Integer, ByVal FilePaths() As String) As Task(Of List(Of MyStructure))
Dim CurMyDesign As New List(Of MyStructure)
Await Task.Run(
Sub()
For j As Integer = FromLineIndex To ToLineIndex
Dim FileLines() As String = File.ReadAllLines(FilePaths(j))
For i = 0 To FileLines.Length - 1
Dim LineContent() As String = FileLines(i).Split(","c)
Dim NewDesign As New MyStructure With {.DateAndTime = Date.Parse(LineContent(0)), .Numbers = (From Num In LineContent Skip 1 Select CInt(Num)).ToArray}
CurMyDesign.Add(NewDesign)
Next
Next
End Sub)
Return CurMyDesign
End Function
Private Async Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim DesignsQuery As New List(Of Task(Of List(Of MyStructure)))
Dim FilesPaths() As String = Directory.GetFiles("c:\users\giannism\documents\visual studio 2015\Projects\WindowsApplication2\WindowsApplication2\bin\Release" & "\Files\")
Dim FilesPaths() As String = Directory.GetFiles(My.Application.Info.DirectoryPath & "\Files\")
Dim IndicesPerIteration As Integer = CInt(Math.Floor(FilesPaths.Length / Environment.ProcessorCount))
MyDesign.Clear()
strMyDesign.Clear()
Button1.Enabled = False
If FilesPaths.Length >= Environment.ProcessorCount Then
For i = 1 To Environment.ProcessorCount
Dim CurIteration As Integer = i
If CurIteration = 1 Then
DesignsQuery.Add(LoadMyDesign(0, IndicesPerIteration - 1, FilesPaths))
ElseIf CurIteration < Environment.ProcessorCount Then
DesignsQuery.Add(LoadMyDesign(((IndicesPerIteration) * (CurIteration - 1)), ((IndicesPerIteration) * CurIteration) - 1, FilesPaths))
Else
DesignsQuery.Add(LoadMyDesign(((IndicesPerIteration) * (CurIteration - 1)), FilesPaths.Length - 1, FilesPaths))
End If
Next
Dim sth As List(Of MyStructure)() = Await Task.WhenAll(DesignsQuery)
For Each Item As List(Of MyStructure) In sth
MyDesign.AddRange(Item)
Next
Else
MyDesign = Await LoadMyDesign(0, FilesPaths.Length - 1, FilesPaths)
End If
strMyDesign.AddRange((From l As MyStructure In MyDesign Select (l.ToString())).Take(10))
ListBox1.DataSource = Nothing
ListBox1.DataSource = strMyDesign
Button1.Enabled = True
End Sub
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
MyDesign.Clear()
strMyDesign.Clear()
ListBox1.DataSource = Nothing
End Sub
End Class
要使其工作,需要在“FilesPaths”变量指向的目录中存在服务器文件
28/8/2016 18:00, 1, 2, 3
28/8/2016 18:01, 4, 5, 6
28/8/2016 18:02, 7, 8, 9
28/8/2016 18:03, 10, 11, 12
28/8/2016 18:04, 1, 2, 3
28/8/2016 18:05, 4, 5, 6
28/8/2016 18:06, 7, 8, 9
28/8/2016 18:07, 10, 11,12
28/8/2016 18:08, 1, 2, 3
28/8/2016 18:09, 4, 5, 6
28/8/2016 18:10, 7, 8, 9
28/8/2016 18:11, 10, 11, 12
28/8/2016 18:12, 1, 2, 3
28/8/2016 18:13, 4, 5, 6
28/8/2016 18:14, 7, 8, 9
28/8/2016 18:15, 10, 11, 12
(P.S。如果你觉得这很有帮助,请给我+声望,因为有些事情需要15岁以上的声誉而且我是新来的,所以还没有得到那个部分)