基本知识
在操作系统中,作业是一种比进程要高层的单位,代表着一次任务。一个作业的执行往往会调用多个进程。实际应用中,我们可以将作业放到后台运行,这样我们就可以在前台执行其他的操作,如Linux中可以用&
来让作业后台执行。Powershell中可以通过Start-Job
在后台执行相应的脚本或命令。
命令用法
名称
Start-Job
语法
Start-Job [-ScriptBlock] <scriptblock> [[-InitializationScript] <scriptblock>] [<CommonParameters>]
Start-Job [-DefinitionName] <string> [[-DefinitionPath] <string>] [[-Type] <string>] [<CommonParameters>]
Start-Job [-FilePath] <string> [[-InitializationScript] <scriptblock>] [<CommonParameters>]
Start-Job [[-InitializationScript] <scriptblock>] [<CommonParameters>]
由语法可见,start-job可以直接将脚本代码块或者是文件形式的脚本代码块设为后台作业。
#Start-Job example
#创建一个睡眠10s的后台作业
$BackgroundJob1 = Start-Job -ScriptBlock {Sleep -Seconds 10}
#将参数传到后台作业中
$a,$b,$c=1,2,0
$Job=Start-Job -ArgumentList $a,$b -ScriptBlock{
param($a,$b)
$c=$a+$b
md "D:\testPowershellFile" #新建文件夹
Write-Host $c #输出结果,命令行不能直接看到,要在job完成后捕获
$c>"D:\testPowershellFile\1.txt" #将内容写到本地
}
Wait-Job -Job $Job #等待后台作业的完成
Receive-Job -Job $Job #获取后台作业的结果
使用后台作业并行
当我们想要并行化一个程序的时候,一个基本化的思路是
1. 将工作分成可以独立执行的几个部分
2. 将每个部分用并行手段执行(多进程,多线程)
3. 收集汇总每个部分的计算结果
我们可以开始多个后台作业同时执行起到并行的作用。接下来用A数组并行化向B数组赋值的场景作为例子。
$B_size=100000
$B=0..($B_size-1)
$taskCount = 10
$arr=0..($taskCount-1)
$A=@() #B copy to A
for($i=0;$i -lt $taskCount;$i++){
$delta=$B_size/$taskCount
$part_B=$B[($i*$delta)..(($i+1)*$delta-1)] #为每个后台作业分配工作
Start-Job -ArgumentList (,$part_B) -ScriptBlock {
param([Object[]]$part_B)
$arr=@()
$count=$part_B.count;
for($j=0;$j -lt $count;$j++){
$arr+=@($part_B[$j])
}
return $arr
} -Name "myJob $i"
}
$count=$taskCount
while($count -gt 0)
{
foreach($job in Get-Job)
{
$state = [string]$job.State
if($state -eq "Completed")
{
Write-Host($job.Name + " 已经完成")
$row=Receive-Job -job $job #收集结果
$A+=$row
$arr[$count-1]=$row
$count--
Remove-Job $job #后台作业完成后要记得将其释放
}
}
#sleep 1
}
"所有任务已完成"
$A.count
总体来说后台作业操作简单,相当于把进程fork出好几个一样的子进程进行作业,本地的命令集也是相同的。但是由于新建和删除后台作业的代价比较大,所以小规模数据如果使用后台作业来并行的话效果可能比串行更糟