- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
这是 Python 中的代码,可以非常快速地生成对数空间值:
import numpy
print(numpy.logspace(0,1,num=10000000))
我尝试用 C++ 模拟其输出,如下所示:
#include <iostream>
#include <cmath>
#include <vector>
std::vector<double> logspace (const double &a, const double &b, const int &k)
{
std::vector<double> logspace;
for (int i = 0; i < k; i++)
{
logspace.push_back(pow(10, i * (b - a) / (k - 1)));
}
return logspace;
}
void logspace_print (std::vector<double> logspace)
{
for (auto ls : logspace)
{
std::cout << ls << "\n";
}
std::cout << "\n";
}
int main ()
{
std::vector<double> my_ls = logspace(0, 1, 10000000);
logspace_print(my_ls);
}
放弃浮点运算,使用函数 pow(., .)
和 for
循环(可能还有很多其他原因),使我的代码作为一个天真的人,例如它的运行时相对于 Python 的人来说非常微弱。我在 Is there something like numpy.logspace in C++? 看到了推荐还。但是,没有明显的区别。那么,我该如何修改我的代码或编写一个与 python 版本相当的新代码呢?
最佳答案
有趣的问题!我的答案在顶部有不同版本的功能。以下只是基准测试代码。使用 google-benchmark 作为库。
std::endl
的刷新,这很好!此外,printf 可能比 std::cout 更快。另请查看 fmtlib 2 .它快速且易于使用。logspace_v3
。)它包括首先运行 linspace
,然后就地计算 10 的幂。 -march=native -mtune=native
和 fast-math)矢量化应该开始。但我不相信它会。这是一些带矢量化的 Godbolt(第 590 行)3 .pow
调用。请注意,这会累积浮点错误并导致不准确的结果。#include <algorithm>
#include <benchmark/benchmark.h>
#include <cmath>
#include <iostream>
#include <numeric>
#include <vector>
#include <gtest/gtest.h>
std::vector<double> logspace(double a, double b, int k) {
std::vector<double> logspace;
for (int i = 0; i < k; i++) {
logspace.push_back(pow(10, i * (b - a) / (k - 1)));
}
return logspace;
}
// Pre-allocate the correct size using .reserve()
std::vector<double> logspace_v1(double a, double b, int k) {
std::vector<double> logspace;
logspace.reserve(k);
for (int i = 0; i < k; i++) {
logspace.push_back(pow(10, i * (b - a) / (k - 1)));
}
return logspace;
}
/// Manually extract the constant factor.
std::vector<double> logspace_v2(double a, double b, int k) {
std::vector<double> logspace;
logspace.reserve(k);
const auto exp_scale = (b - a) / (k - 1);
for (int i = 0; i < k; i++) {
logspace.push_back(pow(10, i * exp_scale));
}
return logspace;
}
/// Copy the impl behavior of numpy.linspace: First linspace then power.
std::vector<double> logspace_v3(double a, double b, int k) {
/*
y = linspace(start, stop, num=num, endpoint=endpoint, axis=axis)
if dtype is None:
return _nx.power(base, y)
return _nx.power(base, y).astype(dtype, copy=False)
*/
const auto exp_scale = (b - a) / (k - 1);
std::vector<double> logspace;
logspace.reserve(k);
for (int i = 0; i < k; i++) {
logspace.push_back(i * exp_scale);
}
std::for_each(logspace.begin(), logspace.end(),
[](double &x) { x = pow(10, x); });
return logspace;
}
/// Improve on v3 by applying pow directly
std::vector<double> logspace_v4(double a, double b, int k) {
const auto exp_scale = (b - a) / (k - 1);
std::vector<double> logspace(k, 0.);
std::generate(logspace.begin(), logspace.end(),
[n = -1, exp_scale]() mutable {
n++;
return pow(10, n * exp_scale);
});
return logspace;
}
/// Use generate_n : First linspace then power.
std::vector<double> logspace_v5(double a, double b, int k) {
const auto exp_scale = (b - a) / (k - 1);
std::vector<double> logspace(k, 0.);
std::iota(logspace.begin(), logspace.end(), 0);
std::for_each(logspace.begin(), logspace.end(),
[exp_scale](double &x) { x *= exp_scale; });
std::for_each(logspace.begin(), logspace.end(),
[](double &x) { x = pow(10, x); });
return logspace;
}
std::vector<double> logspace_v6(double a, double b, int k) {
const auto exp_scale = (b - a) / (k - 1);
const auto factor = pow(10, exp_scale);
std::vector<double> logspace;
logspace.reserve(k);
// val = pow(b, i * exp_scale);
// = pow(pow(b, exp_scale), i);
// = pow(f, i); with f := pow(b, exp_scale);
// next = cur * f;
// first = pow(b, a);
double val = pow(10, a);
for (int i = 0; i < k; i++) {
logspace.push_back(val);
val *= factor;
}
return logspace;
}
template <std::vector<double> (*F)(double, double, int)>
static void LogspaceBench(benchmark::State &state) {
for (auto _ : state) {
benchmark::DoNotOptimize(F(0, 1, state.range(0)));
}
}
BENCHMARK_TEMPLATE(LogspaceBench, logspace)->Arg(1000);
BENCHMARK_TEMPLATE(LogspaceBench, logspace_v1)->Arg(1000);
BENCHMARK_TEMPLATE(LogspaceBench, logspace_v2)->Arg(1000);
BENCHMARK_TEMPLATE(LogspaceBench, logspace_v3)->Arg(1000)->Arg(10000000);
BENCHMARK_TEMPLATE(LogspaceBench, logspace_v4)->Arg(1000);
BENCHMARK_TEMPLATE(LogspaceBench, logspace_v5)->Arg(1000);
BENCHMARK_TEMPLATE(LogspaceBench, logspace_v6)->Arg(1000)->Arg(10000000);
class LogspaceTest
: public testing::TestWithParam<
std::function<std::vector<double>(double, double, int)>> {};
TEST_P(LogspaceTest, IsSame) {
auto func = GetParam();
const auto actual = func(0, 1., 1000);
const auto expected = logspace(0., 1., 1000);
// TODO: Buggy with (3, 70, 1000) and (0, 1, 1000)
ASSERT_EQ(expected.size(), actual.size());
for (int i = 0; i < expected.size(); i++) {
ASSERT_DOUBLE_EQ(actual[i], expected[i]) << i;
}
}
INSTANTIATE_TEST_SUITE_P(InstantiationName, LogspaceTest,
testing::Values(logspace, logspace_v1, logspace_v2,
logspace_v3, logspace_v4, logspace_v5,
logspace_v6));
int main(int argc, char **argv) {
::benchmark::Initialize(&argc, argv);
::benchmark::RunSpecifiedBenchmarks();
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
关于python - 与 numpy.logspace() 函数相比,如何用 C++ 编写更快的代码?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57944012/
这是我用来检查给定图是否为树 (BFS) 的代码。问题是当我使用堆栈 S 时,它不会在 logSpace 中。在浏览一些引用资料时,我想我必须用一些计数器替换堆栈 S,但是怎么做呢?有没有办法修改这个
我正在尝试使用 python 3 和 numpy 创建一个对数刻度的数组。 我的数组边界有问题,返回的数组给出的下限低于我想要的限制。 例如: In : a = np.array(379/19) In
正如标题所说,我正在寻找一些生成对数空间值的函数,就像 numpy.logspace 一样,但适用于 python。和想法? 最佳答案 标准库中没有这样的函数,但是,您可以轻松编写自己的函数。由于 C
我有一个大型数据集(50k 行),我想根据 Y 轴上的密度和 x 轴上的值对数缩放的数据创建直方图,并叠加 KDE 图。 这是正在使用的数据的很小的子集: A B C 1
Numpy linspace 在指定的时间间隔内返回均匀分布的数字。 Numpy logspace 返回在对数刻度上均匀分布的数字。 我不明白为什么 numpy logspace 经常从我设置的边界返
背景和现有解决方案 我正在将一些 Python 代码移植到 Julia (v1.3.1) 中,并且在尝试将代码重现为 Julia 中易于阅读的代码时遇到了问题。 在 Python 中(使用 numpy
这是 Python 中的代码,可以非常快速地生成对数空间值: import numpy print(numpy.logspace(0,1,num=10000000)) 我尝试用 C++ 模拟其输出,如
我正在尝试使用 numpy.logspace() 生成从 1e-10 到 1e-14 的 50 个值。 http://docs.scipy.org/doc/numpy/reference/genera
我是一名优秀的程序员,十分优秀!