在 Go 中以 GMP 风格的性能处理大量数据
Dealing with large numbers with GMP-style performance in Go
我正在学习 Go,我开始使用 math/big
包来处理任意长度的整数。
我编写了这个计算第 n 个斐波那契数的程序:(删除了 import
s):
func main() {
imax, _ := strconv.Atoi(os.Args[1])
var a, b, c big.Int
a.SetUint64(0)
b.SetUint64(1)
for i := 0; i < imax; i++ {
c.Set(&b)
b.Add(&b, &a)
a.Set(&c)
}
fmt.Println(a.String())
}
这是 C 程序的代码:
int main(int argc, char** argv)
{
int imax = atoi(argv[1]);
mpz_t a, b, c;
mpz_inits(a, b, c, NULL);
mpz_set_ui(a, 0);
mpz_set_ui(b, 1);
int i = 0;
for (i = 0; i < imax; i++) {
mpz_swap(a, b);
mpz_add(b, a, b);
}
char* astr = NULL;
astr = mpz_get_str(NULL, 10, a);
printf("%s\n", astr);
return EXIT_SUCCESS;
}
Go 程序在 0.1 秒(平均)内计算出 100,000 项,而使用 GMP 库的 C 等效程序仅在 0.04 秒内运行。那慢了两倍。
有没有办法在我的 Go 程序中获得相同的性能?
一般来说,GMP 速度更快,因为它专为提高性能而设计。在幕后,您可能会发现它有一部分是用汇编编写的,这减少了函数的调用开销,可能会使用一些 CPU 指令,如 ADX
等等。
如果您关心性能,那么您可以使用 mpz_fib_ui
例程,这会更快,因为它从一些数学技巧中获益。
您问题的直接答案可能是使用一些 Go 的 GMP 绑定。
不要打印到标准输出,它很慢。这段代码会得到什么结果?
package main
import (
"math/big"
"os"
"strconv"
)
func main() {
max, err := strconv.Atoi(os.Args[1])
if err != nil {
panic(err)
}
a, b := big.NewInt(0), big.NewInt(1)
for i := 0; i < max; i++ {
a.Add(a, b)
a, b = b, a
}
}
Go 不是手工编写的汇编代码。
您的 100,000 值对于可靠的基准来说太小了。使用 1,000,000 或至少运行十秒的其他值。
我正在学习 Go,我开始使用 math/big
包来处理任意长度的整数。
我编写了这个计算第 n 个斐波那契数的程序:(删除了 import
s):
func main() {
imax, _ := strconv.Atoi(os.Args[1])
var a, b, c big.Int
a.SetUint64(0)
b.SetUint64(1)
for i := 0; i < imax; i++ {
c.Set(&b)
b.Add(&b, &a)
a.Set(&c)
}
fmt.Println(a.String())
}
这是 C 程序的代码:
int main(int argc, char** argv)
{
int imax = atoi(argv[1]);
mpz_t a, b, c;
mpz_inits(a, b, c, NULL);
mpz_set_ui(a, 0);
mpz_set_ui(b, 1);
int i = 0;
for (i = 0; i < imax; i++) {
mpz_swap(a, b);
mpz_add(b, a, b);
}
char* astr = NULL;
astr = mpz_get_str(NULL, 10, a);
printf("%s\n", astr);
return EXIT_SUCCESS;
}
Go 程序在 0.1 秒(平均)内计算出 100,000 项,而使用 GMP 库的 C 等效程序仅在 0.04 秒内运行。那慢了两倍。
有没有办法在我的 Go 程序中获得相同的性能?
一般来说,GMP 速度更快,因为它专为提高性能而设计。在幕后,您可能会发现它有一部分是用汇编编写的,这减少了函数的调用开销,可能会使用一些 CPU 指令,如 ADX
等等。
如果您关心性能,那么您可以使用 mpz_fib_ui
例程,这会更快,因为它从一些数学技巧中获益。
您问题的直接答案可能是使用一些 Go 的 GMP 绑定。
不要打印到标准输出,它很慢。这段代码会得到什么结果?
package main
import (
"math/big"
"os"
"strconv"
)
func main() {
max, err := strconv.Atoi(os.Args[1])
if err != nil {
panic(err)
}
a, b := big.NewInt(0), big.NewInt(1)
for i := 0; i < max; i++ {
a.Add(a, b)
a, b = b, a
}
}
Go 不是手工编写的汇编代码。
您的 100,000 值对于可靠的基准来说太小了。使用 1,000,000 或至少运行十秒的其他值。