taskset


taskset命令用于设置或查询进程所在的CPU逻辑核心,设置进程(或线程)的处理器亲和性(Processor Affinity),可以将其绑定到特定的一个或多个CPU上去执行,而不允许系统将进线程调度到其他的CPU上。
它是 Linux 系统当中用于查看、设定 CPU 核使用情况的命令。将进程绑定到指定的CPU上运行,这样可以避免大量的进程切换产生的无效时间。通过taskset可将某个进程与某个CPU核心绑定,使得其仅在与之绑定的CPU核心上运行。线程是最小的内核执行调度单元,准确地说是将某个线程与某个CPU核心绑定,而非某个进程。它依据线程PID(TID)查询或设置线程的CPU亲和性。
taskset is used to set or retrieve the CPU affinity of a running process given its pid, or to launch a new command with a given CPU affinity. CPU affinity is a scheduler property that "bonds" a process to a given set of CPUs on the system. The Linux scheduler will honor the given CPU affinity and the process will not run on any other CPUs. Note that the Linux scheduler also supports natural CPU affinity: the scheduler attempts to keep processes on the same CPU as long as practi? cal for performance reasons. Therefore, forcing a specific CPU affinity is useful only in certain applications.
The CPU affinity is represented as a bitmask, with the lowest order bit corresponding to the first logical CPU and the highest order bit corre? sponding to the last logical CPU. Not all CPUs may exist on a given system but a mask may specify more CPUs than are present. A retrieved mask will reflect only the bits that correspond to CPUs physically on the system. If an invalid mask is given (i.e., one that corresponds to no valid CPUs on the current system) an error is returned. The masks may be specified in hexadecimal (with or without a leading "0x"), or as a CPU list with the --cpu-list option.
语法
taskset [options] mask command [arg]...
taskset [options] -p [mask] pid
命令描述
taskset 命令用于设置或者获取一直指定的 PID 对于 CPU 核的运行依赖关系。也可以用它来启动一个命令,直接设置它的 CPU 核的运行依赖关系。
CPU 核依赖关系是指程序会被在指定的 CPU 核中运行,而不会再其它 CPU 核中运行的一种调度关系。需要说明的是,在正常情况下,为了系统性能的原因,调度器会尽可能的在一个 CPU 核中维持一个进程的执行。强制指定特殊的 CPU 核依赖关系对于特殊的应用是有意义的。
CPU 核的定义采用二进制位定义的方式进行,最低位代表 CPU0,然后依次排序。这种位定义可以超过系统实际的 CPU 总数,并不会存在问题。通过命令获得的这种 CPU 位标记,只会包含系统实际 CPU 的数目。如果设定的位标记少于系统 CPU 的实际数目,那么命令会产生一个错误。当然这种给定的和获取的位标记采用十六进制标识。
常用参数
-a, –all-tasks 设置或检索所有任务(线程)的CPU相关性对于给定的PID
-c, –cpu-list 将掩码解释为处理器的数字列表
-p, –pid 在现有PID上操作,不要启动新任务
-V, –version 显示版本信息
-h, –help 显示帮助信息
使用描述
-p, --pid 对一个现有的进程进行操作,而不是启动一个新的进程
-c, --cpu-list 使用 CPU 编号替代位标记,这可以是一个列表,列表中可以使用逗号分隔,或者使用 "-" 进行范围标记,例如:0,5,7,9-11
使用默认的行为,用给定的 CPU 核运行位标记运行一个进程
taskset mask command [arguments]
Run a command with given affinity mask
taskset [options] -p [mask] pid
Set the affinity of CPU of an existing task
taskset -p pid
fetch the affinity of CPU of an existing task
获取一个指定进程的 CPU 核运行位标记
taskset -p pid
设定一个指定进程的 CPU 核运行位标记
taskset -p mask pid
taskset -c 0,10 ./freeoa
让程序freeoa执行于0和10号逻辑核心上
不设置CPU绑定 ./freeoa
设置绑定到0号CPU逻辑核心 taskset -c 0 ./freeoa
设置绑定到0,1号CPU逻辑核心 taskset -c 0,1 ./freeoa
设置绑定到0,1,2号CPU逻辑核心 taskset -c 0,1,2 ./freeoa
CPU资源密集型的场景下当启动两个线程时,绑定一个核心的处理能力是绑定两个核心的处理能力的50%左右;而绑定的核心数超过线程数时(如绑定到0,1,2号逻辑核心),其效率并没有明显提高。强制指定特殊的 CPU 核依赖关系对于特殊的应用是有意义的。CPU 核的定义采用位定义的方式进行,最低位代表 CPU0,然后依次排序。这种位定义可以超过系统实际的 CPU 总数,并不会存在问题。通过命令获得的这种 CPU 位标记,只会包含系统实际 CPU 的数目。如果设定的位标记少于系统 CPU 的实际数目,那么命令会产生一个错误。当然这种给定的和获取的位标记采用 16 进制标识:
0x00000001 代表 #0 CPU
0x00000003 代表 #0 和 #1 CPU
0x00000007 代表 #0 和 #1、2 CPU
0xFFFFFFFF 代表 #0 到 #31 CPU
# taskset -p 1393
pid 1393's current affinity mask: ff
输出结构处理器亲和性掩码是ff,表示进程(或线程)可以在主机上让任何一个CPU运行。查看进程(或线程)运行CPU范围使用-c参数。由于主机的CPU是4核心且支持超线程,因此有8颗逻辑CPU。
# taskset -cp 1389
pid 1389's current affinity list: 0-7
更改进程(或线程)CPU亲和性
taskset -p hexadecimal mask PID/LWP
上面1393号线程可以在0~7号CPU之间运行,现在设置掩码0x11(二进制0001 0001),表示可以在0、4号CPU上运行。
# taskset -p 0x11 1393
pid 1393's current affinity mask: ff
pid 1393's new affinity mask: 11
# taskset -p 1393
pid 1393's current affinity mask: 11
# taskset -cp 1393
pid 1393's current affinity list: 0,4
为具体某一进程(或 线程)CPU亲和性指定一组范围
使用-c参数
# taskset -cp 0,3 1393
pid 1393's current affinity list: 0,4
pid 1393's new affinity list: 0,3
# taskset -cp 1393
pid 1393's current affinity list: 0,3
为某进程即时分配段连续的CPU,可以使用英文的'-'来取代','。
# taskset -c 0-3 firefox
软件信息
taskset 命令属于 util-linux-ng 包,通过sched_getcpu函数不停检测当前占用的逻辑核心编号,另外可以通过top(top -p pid)指令来查看对相应的进程的设置是否生效。
参考命令
chrt, nice, renice, sched_setaffinity, sched_getaffinity
权限要求
如果需要设定,那么需要拥有 CAP_SYS_NICE 的权限;如果要获取设定信息,没有任何权限要求。
参考来源
taskset(1)
程序绑定到核心和CPU亲和性
常使用 taskset 来将应用程序绑定到一个核或者多个核上,这种机制叫做 CPU 亲和性 (CPU affinity)。
taskset 是一个 Linux 命令行工具,用于设置或检索一个进程的 CPU 亲和性(CPU affinity)。CPU 亲和性决定了一个进程可以运行在哪个 CPU 或 CPU 核心上。 合理设置 CPU 亲和性可以带来以下好处:
1.减少缓存丢失,提高缓存命中率
2.降低线程迁移和上下文切换开销
3.分配独占资源,避免资源争用
4.均衡负载,充分利用多核 CPU
taskset 使用方法
taskset 命令的主要用法如下。
1.获取进程的 CPU 亲和性
taskset -p <PID>
该命令会显示进程 ID 为 <PID> 的进程当前的 CPU 亲和性掩码 (affinity mask)。
2.设置进程的 CPU 亲和性
taskset -p <MASK> <PID>
该命令将进程 ID 为 <PID> 的进程的 CPU 亲和性设置为 <MASK> 指定的 CPU 掩码。
CPU 掩码是一个十六进制数,用于表示要被绑定的 CPU 核心。例如在一个 4 核心的系统中,0x1 表示只绑定到第一个 CPU 核心,0x5(bin:0101) 表示绑定到第 1 个和第 3 个 CPU 核心。哪一个二进制位上为 1 就会绑定到哪个核上。
3.启动新进程并设置其 CPU 亲和性
taskset <MASK> <COMMAND> [ARGUMENTS...]
该命令会使用 <MASK> 指定的 CPU 亲和性启动一个新进程,运行命令 <COMMAND> 及其参数 [ARGUMENTS...]。
4.其他选项
taskset 还提供了其他一些有用的选项:
-c: 使用 CPU 列表格式指定 CPU 掩码, 例如 taskset -c 0,5,7,9-11 ./program
-a: 获取或设置进程及其所有线程的 CPU 亲和性
例子:
默认行为是运行一条新命令:
taskset 03 sshd -b 1024
可以获取现有任务(pid为700,下同)的掩码:
taskset -p 700
或设置掩码:
taskset -p 03 700
使用逗号分隔的列表格式而不是掩码:
taskset -pc 0,3,7-11 700
列表格式中的范围可以带一个跨度参数:
例如 0-31:2 与掩码 0x55555555 等效
子进程的 CPU 亲和性
Linux 默认子进程会继承父进程的 CPU 亲和性,以保持亲和性的连续性。但如果有需要, 用户依然可以手动设置属于它的子进程或线程的 CPU 亲和性,以优化 CPU 资源利用和程序性能。如果想修改其他用户的进程的 CPU 亲和性,需要 root 权限或者拥有 CAP_SYS_NICE 权限。
任何用户都可以获取任意进程的 CPU 亲和性掩码。
运行时设置 CPU 亲和性
当然程序在运行时也可以调用 taskset 命令设置 CPU 亲和性,比如下面的 Go 代码, 会将程序本身绑定到前两个 CPU 核上:
package main
import (
"fmt"
"os"
"os/exec"
)
func main() {
pid := os.Getpid()
// 获取当前进程的 CPU 亲和性
cmd := exec.Command("taskset", "-p", fmt.Sprintf("%d", pid))
out, err := cmd.Output()
if err != nil {
fmt.Println(err)
}
// 设置当前进程的 CPU 亲和性为 CPU 0 和 CPU 1
cmd = exec.Command("taskset", "-p", "0,1", fmt.Sprintf("%d", pid))
out, err = cmd.Output()
if err != nil {
fmt.Println(err)
}
fmt.Printf("%s", out)
}
实际上也可以调用系统调用sched_setaffinity来绑核,使用sched_getaffinity来查询 CPU 的亲和性:
package main
import (
"fmt"
"syscall"
"time"
"unsafe"
)
func main() {
var mask uintptr
// 获取当前进程的 CPU 亲和性
if _, _, err := syscall.RawSyscall(syscall.SYS_SCHED_GETAFFINITY, 0, uintptr(unsafe.Sizeof(mask)), uintptr(unsafe.Pointer(&mask))); err != 0 {
fmt.Println("failed to get CPU affinity:", err)
return
}
fmt.Println("current CPU affinity:", mask)
// 设置当前进程的 CPU 亲和性为 CPU 0 和 CPU 1
mask = 3
if _, _, err := syscall.RawSyscall(syscall.SYS_SCHED_SETAFFINITY, 0, uintptr(unsafe.Sizeof(mask)), uintptr(unsafe.Pointer(&mask))); err != 0 {
fmt.Println("failed to set CPU affinity:", err)
return
}
fmt.Println("new CPU affinity:", mask)
for {
println("Hello, World!")
time.Sleep(1 * time.Second)
}
}
它是 Linux 系统当中用于查看、设定 CPU 核使用情况的命令。将进程绑定到指定的CPU上运行,这样可以避免大量的进程切换产生的无效时间。通过taskset可将某个进程与某个CPU核心绑定,使得其仅在与之绑定的CPU核心上运行。线程是最小的内核执行调度单元,准确地说是将某个线程与某个CPU核心绑定,而非某个进程。它依据线程PID(TID)查询或设置线程的CPU亲和性。
taskset is used to set or retrieve the CPU affinity of a running process given its pid, or to launch a new command with a given CPU affinity. CPU affinity is a scheduler property that "bonds" a process to a given set of CPUs on the system. The Linux scheduler will honor the given CPU affinity and the process will not run on any other CPUs. Note that the Linux scheduler also supports natural CPU affinity: the scheduler attempts to keep processes on the same CPU as long as practi? cal for performance reasons. Therefore, forcing a specific CPU affinity is useful only in certain applications.
The CPU affinity is represented as a bitmask, with the lowest order bit corresponding to the first logical CPU and the highest order bit corre? sponding to the last logical CPU. Not all CPUs may exist on a given system but a mask may specify more CPUs than are present. A retrieved mask will reflect only the bits that correspond to CPUs physically on the system. If an invalid mask is given (i.e., one that corresponds to no valid CPUs on the current system) an error is returned. The masks may be specified in hexadecimal (with or without a leading "0x"), or as a CPU list with the --cpu-list option.
语法
taskset [options] mask command [arg]...
taskset [options] -p [mask] pid
命令描述
taskset 命令用于设置或者获取一直指定的 PID 对于 CPU 核的运行依赖关系。也可以用它来启动一个命令,直接设置它的 CPU 核的运行依赖关系。
CPU 核依赖关系是指程序会被在指定的 CPU 核中运行,而不会再其它 CPU 核中运行的一种调度关系。需要说明的是,在正常情况下,为了系统性能的原因,调度器会尽可能的在一个 CPU 核中维持一个进程的执行。强制指定特殊的 CPU 核依赖关系对于特殊的应用是有意义的。
CPU 核的定义采用二进制位定义的方式进行,最低位代表 CPU0,然后依次排序。这种位定义可以超过系统实际的 CPU 总数,并不会存在问题。通过命令获得的这种 CPU 位标记,只会包含系统实际 CPU 的数目。如果设定的位标记少于系统 CPU 的实际数目,那么命令会产生一个错误。当然这种给定的和获取的位标记采用十六进制标识。
常用参数
-a, –all-tasks 设置或检索所有任务(线程)的CPU相关性对于给定的PID
-c, –cpu-list 将掩码解释为处理器的数字列表
-p, –pid 在现有PID上操作,不要启动新任务
-V, –version 显示版本信息
-h, –help 显示帮助信息
使用描述
-p, --pid 对一个现有的进程进行操作,而不是启动一个新的进程
-c, --cpu-list 使用 CPU 编号替代位标记,这可以是一个列表,列表中可以使用逗号分隔,或者使用 "-" 进行范围标记,例如:0,5,7,9-11
使用默认的行为,用给定的 CPU 核运行位标记运行一个进程
taskset mask command [arguments]
Run a command with given affinity mask
taskset [options] -p [mask] pid
Set the affinity of CPU of an existing task
taskset -p pid
fetch the affinity of CPU of an existing task
获取一个指定进程的 CPU 核运行位标记
taskset -p pid
设定一个指定进程的 CPU 核运行位标记
taskset -p mask pid
taskset -c 0,10 ./freeoa
让程序freeoa执行于0和10号逻辑核心上
不设置CPU绑定 ./freeoa
设置绑定到0号CPU逻辑核心 taskset -c 0 ./freeoa
设置绑定到0,1号CPU逻辑核心 taskset -c 0,1 ./freeoa
设置绑定到0,1,2号CPU逻辑核心 taskset -c 0,1,2 ./freeoa
CPU资源密集型的场景下当启动两个线程时,绑定一个核心的处理能力是绑定两个核心的处理能力的50%左右;而绑定的核心数超过线程数时(如绑定到0,1,2号逻辑核心),其效率并没有明显提高。强制指定特殊的 CPU 核依赖关系对于特殊的应用是有意义的。CPU 核的定义采用位定义的方式进行,最低位代表 CPU0,然后依次排序。这种位定义可以超过系统实际的 CPU 总数,并不会存在问题。通过命令获得的这种 CPU 位标记,只会包含系统实际 CPU 的数目。如果设定的位标记少于系统 CPU 的实际数目,那么命令会产生一个错误。当然这种给定的和获取的位标记采用 16 进制标识:
0x00000001 代表 #0 CPU
0x00000003 代表 #0 和 #1 CPU
0x00000007 代表 #0 和 #1、2 CPU
0xFFFFFFFF 代表 #0 到 #31 CPU
# taskset -p 1393
pid 1393's current affinity mask: ff
输出结构处理器亲和性掩码是ff,表示进程(或线程)可以在主机上让任何一个CPU运行。查看进程(或线程)运行CPU范围使用-c参数。由于主机的CPU是4核心且支持超线程,因此有8颗逻辑CPU。
# taskset -cp 1389
pid 1389's current affinity list: 0-7
更改进程(或线程)CPU亲和性
taskset -p hexadecimal mask PID/LWP
上面1393号线程可以在0~7号CPU之间运行,现在设置掩码0x11(二进制0001 0001),表示可以在0、4号CPU上运行。
# taskset -p 0x11 1393
pid 1393's current affinity mask: ff
pid 1393's new affinity mask: 11
# taskset -p 1393
pid 1393's current affinity mask: 11
# taskset -cp 1393
pid 1393's current affinity list: 0,4
为具体某一进程(或 线程)CPU亲和性指定一组范围
使用-c参数
# taskset -cp 0,3 1393
pid 1393's current affinity list: 0,4
pid 1393's new affinity list: 0,3
# taskset -cp 1393
pid 1393's current affinity list: 0,3
为某进程即时分配段连续的CPU,可以使用英文的'-'来取代','。
# taskset -c 0-3 firefox
软件信息
taskset 命令属于 util-linux-ng 包,通过sched_getcpu函数不停检测当前占用的逻辑核心编号,另外可以通过top(top -p pid)指令来查看对相应的进程的设置是否生效。
参考命令
chrt, nice, renice, sched_setaffinity, sched_getaffinity
权限要求
如果需要设定,那么需要拥有 CAP_SYS_NICE 的权限;如果要获取设定信息,没有任何权限要求。
参考来源
taskset(1)
程序绑定到核心和CPU亲和性
常使用 taskset 来将应用程序绑定到一个核或者多个核上,这种机制叫做 CPU 亲和性 (CPU affinity)。
taskset 是一个 Linux 命令行工具,用于设置或检索一个进程的 CPU 亲和性(CPU affinity)。CPU 亲和性决定了一个进程可以运行在哪个 CPU 或 CPU 核心上。 合理设置 CPU 亲和性可以带来以下好处:
1.减少缓存丢失,提高缓存命中率
2.降低线程迁移和上下文切换开销
3.分配独占资源,避免资源争用
4.均衡负载,充分利用多核 CPU
taskset 使用方法
taskset 命令的主要用法如下。
1.获取进程的 CPU 亲和性
taskset -p <PID>
该命令会显示进程 ID 为 <PID> 的进程当前的 CPU 亲和性掩码 (affinity mask)。
2.设置进程的 CPU 亲和性
taskset -p <MASK> <PID>
该命令将进程 ID 为 <PID> 的进程的 CPU 亲和性设置为 <MASK> 指定的 CPU 掩码。
CPU 掩码是一个十六进制数,用于表示要被绑定的 CPU 核心。例如在一个 4 核心的系统中,0x1 表示只绑定到第一个 CPU 核心,0x5(bin:0101) 表示绑定到第 1 个和第 3 个 CPU 核心。哪一个二进制位上为 1 就会绑定到哪个核上。
3.启动新进程并设置其 CPU 亲和性
taskset <MASK> <COMMAND> [ARGUMENTS...]
该命令会使用 <MASK> 指定的 CPU 亲和性启动一个新进程,运行命令 <COMMAND> 及其参数 [ARGUMENTS...]。
4.其他选项
taskset 还提供了其他一些有用的选项:
-c: 使用 CPU 列表格式指定 CPU 掩码, 例如 taskset -c 0,5,7,9-11 ./program
-a: 获取或设置进程及其所有线程的 CPU 亲和性
例子:
默认行为是运行一条新命令:
taskset 03 sshd -b 1024
可以获取现有任务(pid为700,下同)的掩码:
taskset -p 700
或设置掩码:
taskset -p 03 700
使用逗号分隔的列表格式而不是掩码:
taskset -pc 0,3,7-11 700
列表格式中的范围可以带一个跨度参数:
例如 0-31:2 与掩码 0x55555555 等效
子进程的 CPU 亲和性
Linux 默认子进程会继承父进程的 CPU 亲和性,以保持亲和性的连续性。但如果有需要, 用户依然可以手动设置属于它的子进程或线程的 CPU 亲和性,以优化 CPU 资源利用和程序性能。如果想修改其他用户的进程的 CPU 亲和性,需要 root 权限或者拥有 CAP_SYS_NICE 权限。
任何用户都可以获取任意进程的 CPU 亲和性掩码。
运行时设置 CPU 亲和性
当然程序在运行时也可以调用 taskset 命令设置 CPU 亲和性,比如下面的 Go 代码, 会将程序本身绑定到前两个 CPU 核上:
package main
import (
"fmt"
"os"
"os/exec"
)
func main() {
pid := os.Getpid()
// 获取当前进程的 CPU 亲和性
cmd := exec.Command("taskset", "-p", fmt.Sprintf("%d", pid))
out, err := cmd.Output()
if err != nil {
fmt.Println(err)
}
// 设置当前进程的 CPU 亲和性为 CPU 0 和 CPU 1
cmd = exec.Command("taskset", "-p", "0,1", fmt.Sprintf("%d", pid))
out, err = cmd.Output()
if err != nil {
fmt.Println(err)
}
fmt.Printf("%s", out)
}
实际上也可以调用系统调用sched_setaffinity来绑核,使用sched_getaffinity来查询 CPU 的亲和性:
package main
import (
"fmt"
"syscall"
"time"
"unsafe"
)
func main() {
var mask uintptr
// 获取当前进程的 CPU 亲和性
if _, _, err := syscall.RawSyscall(syscall.SYS_SCHED_GETAFFINITY, 0, uintptr(unsafe.Sizeof(mask)), uintptr(unsafe.Pointer(&mask))); err != 0 {
fmt.Println("failed to get CPU affinity:", err)
return
}
fmt.Println("current CPU affinity:", mask)
// 设置当前进程的 CPU 亲和性为 CPU 0 和 CPU 1
mask = 3
if _, _, err := syscall.RawSyscall(syscall.SYS_SCHED_SETAFFINITY, 0, uintptr(unsafe.Sizeof(mask)), uintptr(unsafe.Pointer(&mask))); err != 0 {
fmt.Println("failed to set CPU affinity:", err)
return
}
fmt.Println("new CPU affinity:", mask)
for {
println("Hello, World!")
time.Sleep(1 * time.Second)
}
}