使用Go对CPU ID进行位掩码转换 [英] Bitmasking conversion of CPU ids with Go

查看:96
本文介绍了使用Go对CPU ID进行位掩码转换的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个掩码,其中包含二进制计数的cpu_ids(对于3个CPU,为0xA00000800000),我想将其转换为逗号分隔的cpu_ids的string:"0,2,24".

I have a mask that contains a binary counting of cpu_ids (0xA00000800000 for 3 CPUs) which I want to convert into a string of comma separated cpu_ids: "0,2,24".

我执行了以下Go实施(我是Go入门).这是最好的方法吗?尤其是字节缓冲区的处理似乎效率低下!

I did the following Go implementation (I am a Go starter). Is it the best way to do it? Especially the handling of byte buffers seems to be inefficient!

package main

import (
    "fmt"
    "os"
    "os/exec"
)

func main(){
    cpuMap     := "0xA00000800000"
    cpuIds     = getCpuIds(cpuMap)
    fmt.Println(cpuIds)
}

func getCpuIds(cpuMap string) string {
    // getting the cpu ids
    cpu_ids_i, _ := strconv.ParseInt(cpuMap, 0, 64) // int from string
    cpu_ids_b := strconv.FormatInt(cpu_ids_i, 2)    // binary as string

    var buff bytes.Buffer
    for i, runeValue := range cpu_ids_b {
        // take care! go returns code points and not the string    
        if runeValue == '1' {
            //fmt.Println(bitString, i)
            buff.WriteString(fmt.Sprintf("%d", i))
        }
        if (i+1 < len(cpu_ids_b)) && (runeValue == '1') {
            //fmt.Println(bitString)
            buff.WriteString(string(","))
        }

    }
    cpuIds := buff.String()
    // remove last comma
    cpuIds = cpuIds[:len(cpuIds)-1]
    //fmt.Println(cpuIds)
    return cpuIds
}

返回:

"0,2,24"

"0,2,24"

推荐答案

您要做的实际上是从左至右输出二进制表示形式的"1"的索引,并从左边(不寻常).

What you're doing is essentially outputting the indices of the "1"'s in the binary representation from left-to-right, and starting index counting from the left (unusal).

您可以使用位掩码和按位运算符来实现相同功能,而无需将其转换为二进制字符串.而且我将返回索引的一部分,而不是其格式化的字符串,以便于使用.

You can achieve the same using bitmasks and bitwise operators, without converting it to a binary string. And I would return a slice of indices instead of its formatted string, easier to work with.

要测试最低(最右边)位是否为1,您可以像x&0x01 == 1一样进行操作,并将整数向右移:x >>= 1.移位后,最右边的位消失",先前的第二位变为第一位,因此您可以使用相同的逻辑再次进行测试.您可以循环播放直到该数字大于0(这意味着底数为1位)为止.

To test if the lowest (rightmost) bit is 1, you can do it like x&0x01 == 1, and to shift a whole number bitwise to the right: x >>= 1. After a shift, the rightmost bit "disappears", and the previously 2nd bit becomes the 1st, so you can test again with the same logic. You may loop until the number is greater than 0 (which means it sill has 1-bits).

有关此按位运算的更多示例,请参见此问题:某些运算符之间的差异";; |;,"^",&",& ^". Golang

See this question for more examples of bitwise operations: Difference between some operators "|", "^", "&", "&^". Golang

当然,如果我们测试最右边的位并向右移动,我们会以 reverse 的顺序(与您想要的相比)获得位(索引),并且索引从右边开始计数,因此我们在返回结果之前必须更正此问题.

Of course if we test the rightmost bit and shift right, we get the bits (indices) in reverse order (compared to what you want), and the indices are counted from right, so we have to correct this before returning the result.

所以解决方案如下:

func getCpuIds(cpuMap string) (r []int) {
    ci, err := strconv.ParseInt(cpuMap, 0, 64)
    if err != nil {
        panic(err)
    }

    count := 0
    for ; ci > 0; count, ci = count+1, ci>>1 {
        if ci&0x01 == 1 {
            r = append(r, count)
        }
    }

    // Indices are from the right, correct it:
    for i, v := range r {
        r[i] = count - v - 1
    }
    // Result is in reverse order:
    for i, j := 0, len(r)-1; i < j; i, j = i+1, j-1 {
        r[i], r[j] = r[j], r[i]
    }

    return
}

输出(在游乐场上尝试):

[0 2 24]

如果出于某种原因您需要将结果作为逗号分隔的string,则可以通过以下方式获得该信息:

If for some reason you need the result as a comma separated string, this is how you can obtain that:

buf := &bytes.Buffer{}
for i, v := range cpuIds {
    if i > 0 {
        buf.WriteString(",")
    }
    buf.WriteString(strconv.Itoa(v))
}
cpuIdsStr := buf.String()
fmt.Println(cpuIdsStr)

输出(在游乐场上尝试):

0,2,24

这篇关于使用Go对CPU ID进行位掩码转换的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆