对于我在Linux Kernel上的课程项目,我需要模拟由于内存不足而导致大量页面交换的情况.
我想编写一个需要大量物理内存的程序,因此该程序访问的页面必须多次交换.
我在中C++和中进行了以下实现:并在Rvia中使用它Rcpp:
// [[Rcpp::export]]
double median2(std::vector<double> x){
double median;
size_t size = x.size();
sort(x.begin(), x.end());
if (size % 2 == 0){
median = (x[size / 2 - 1] + x[size / 2]) / 2.0;
}
else {
median = x[size / 2];
}
return median;
}
Run Code Online (Sandbox Code Playgroud)
如果我随后将性能与标准内置R中值函数进行比较,我会得到以下结果 microbenchmark
> x = rnorm(100)
> microbenchmark(median(x),median2(x))
Unit: microseconds
expr min lq mean median uq max neval
median(x) 25.469 26.990 34.96888 28.130 29.081 518.126 100
median2(x) 1.140 1.521 …Run Code Online (Sandbox Code Playgroud) 任何人都可以解释为什么以下两个部分之间存在性能差异?统计上显着的是,第二个定时器呼叫报告的数量小于第一个定时器呼叫的数量.我唯一的想法是Netlogo可以在内存中缓存海龟.这是预期的行为还是有错误?
to setup
clear-all
crt 100
let repetitions 10000
;;Timing assigning x to self
reset-timer
repeat repetitions
[
ask turtles
[
let x self
]
]
show timer
;;Timing assigning x to who of self
reset-timer
repeat repetitions
[
ask turtles
[
let x [who] of self
]
]
show timer
end
Run Code Online (Sandbox Code Playgroud) 我使用任意精度整数来表示密集的位向量 - 大小从十几到几千不等.
我的代码经常需要检查是否设置了某些位,所以我做了一些微基准测试,看看某些变化是否明显快于其他变量:
bench_1(0, _, _) :- !. bench_1(N, V, P) :- V /\ (1 << P) =\= 0, N0 is N-1, bench_1(N0, V, P). bench_2(0, _, _) :- !. bench_2(N, V, P) :- (V >> P) /\ 1 =:= 1, N0 is N-1, bench_2(N0, V, P). bench_3(0, _, _) :- !. bench_3(N, V, P) :- (V >> P) /\ 1 =\= 0, N0 is N-1, bench_3(N0, V, P). bench_4(0, _, _) :- !. bench_4(N, V, P) :- (V >> P) /\ …
我正在开发一个绘制动物园对象的函数,因此我正在使用microbenchmark对各种选项的执行速度进行基准测试。
但是,每次运行microbenchmark我都会收到以下错误:
警告信息:
在 microbenchmark::microbenchmark(overlapping_base,overlapping_lattice, : 无法测量 2524 次评估的正执行时间。
每次运行代码时,评估的值都会发生变化。
我的猜测是基准测试的执行无法完成。这意味着每次运行microbenchmark我都会得到非常不同的响应(这极大地改变了执行速度)。因此,我无法确定哪种绘图方法最快。
我正在使用的代码:
library(lattice)
library(ggplot2)
library(zoo)
z <- structure(c(-0.02838132, -0.02642141, -0.02511601, -0.02443906,
-0.02414024, -0.02417388, -0.02451562, -0.02393946, -0.02242496,
-0.02104852, 0.01739089, 0.01981665, 0.02210309, 0.02376982,
0.02496479, 0.02538433, 0.02558674, 0.02642987, 0.02848319, 0.0305888,
-0.02174604, -0.01987625, -0.01885374, -0.01837707, -0.01820114,
-0.01826306, -0.01862707, -0.01826593, -0.01710169, -0.01580846,
-0.00849795, -0.00590564, -0.00353068, -0.00165086, -0.00038422,
0.00032302, 0.00035668, 0.00161519, 0.00415983, 0.00657286, 0.00965842,
0.01212343, 0.01442211, 0.01579477, 0.01667243, 0.01666898, 0.01611297,
0.01692785, 0.01928281, 0.02143322, -0.0194464, -0.01757103,
-0.0158406, -0.01457289, -0.01380771, -0.0135324, -0.0140401, …Run Code Online (Sandbox Code Playgroud) 是否可以通过微基准评估包含多行代码的代码块?如果是这样,怎么办?
示例:在字符列中有一些数字数据:
testdata <- tibble::tibble(col1 = runif(1000), col2 = as.character(runif(1000)), col3 = as.character(runif(1000)))
Run Code Online (Sandbox Code Playgroud)
现在我们可以尝试不同的方式来转换它们。我们可以在列上直接调用as.numeric:
testdata$col2 <- as.numeric(testdata$col2)
testdata$col3 <- as.numeric(testdata$col3)
Run Code Online (Sandbox Code Playgroud)
我们可以尝试在dplyrmutate中进行操作:
testdata <- dplyr::mutate(testdata, col2 = as.numeric(col2),
col3 = as.numeric(col3))
Run Code Online (Sandbox Code Playgroud)
或者,也许我们知道所有列都应为数字,所以我们可以尝试使用不太明确的方法进行检查:
testdata <- dplyr::mutate_if(testdata, .predicate = is.character, .funs = as.numeric)
Run Code Online (Sandbox Code Playgroud)
现在我们要比较这三个选项的性能。
后两个选项是单独的调用,因此可以在微基准测试中轻松测试它们,但是第一个选项包括两个单独的调用。我们可以将两个调用包装在一个函数中,然后在微基准测试中对其进行评估,但这会引入该函数的少量开销,因此从技术上讲,我们不在评估我们现在拥有的解决方案。我们可以将调用分别包含在微基准中,然后将它们加起来,因为平均值应该可以,但是对于最小值或最大值之类的东西,不一定能得出明智的结果。
微基准测试文档中的示例大多使用简单的单个表达式,并且经常使用简单的函数来包装代码。
是否可以将多行代码直接输入到微基准中以便一起评估?
我对STREAM(http://www.cs.virginia.edu/stream/ref.html#runrules)基准测试有一些疑问。
* (a) Each array must be at least 4 times the size of the
* available cache memory. I don't worry about the difference
* between 10^6 and 2^20, so in practice the minimum array size
* is about 3.8 times the cache size.
Run Code Online (Sandbox Code Playgroud)
例如,我添加了两个额外的数组,并确保将它们与原始a / b / c数组一起访问。我相应地修改了字节记帐。使用这两个额外的阵列,我的带宽数量增加了约11.5%。
> diff stream.c modified_stream.c
181c181,183
< c[STREAM_ARRAY_SIZE+OFFSET];
---
> c[STREAM_ARRAY_SIZE+OFFSET],
> e[STREAM_ARRAY_SIZE+OFFSET],
> d[STREAM_ARRAY_SIZE+OFFSET];
192,193c194,195
< 3 * sizeof(STREAM_TYPE) * STREAM_ARRAY_SIZE,
< 3 * sizeof(STREAM_TYPE) * …Run Code Online (Sandbox Code Playgroud) benchmarking cpu-architecture microbenchmark memory-bandwidth
所以,我想看看我的代码中的函数需要多长时间才能运行。(实时)。最初,我有这个:
clock_t begin = clock();
my_function();
clock_t end = clock();
double time_spent = (double)(end - begin);
Run Code Online (Sandbox Code Playgroud)
但显然,这种方法存在一些问题。
那么,获取函数运行时间的正确方法是什么?CPU 时间真的是正确的方法吗?我可以测量多精确?我在想纳秒级?
在优化我们的代码库时,我们尝试使用 bang 方法来减少有意义的对象分配,但我们在基准测试中观察到分配的对象数量减少但整体内存大小增加。
复制脚本:
# frozen_string_literal: true
require 'bundler/inline'
gemfile(true) do
source "https://rubygems.org"
git_source(:github) { |repo| "https://github.com/#{repo}.git" }
gem 'benchmark-memory', '0.1.2'
end
require 'benchmark/memory'
def with_bang(*methods)
methods.tap(&:flatten!)
end
def without_bang(*methods)
methods.flatten
end
Benchmark.memory do |x|
x.report("with_bang") { with_bang(:a, :b, :c, :d, :e, :f, :g, :h, :i, :j, :k, :l, :m, :n, :o) }
x.report("without_bang") { without_bang(:a, :b, :c, :d, :e, :f, :g, :h, :i, :j, :k, :l, :m, :n, :o) }
x.compare!
end
# Output
# Ruby version: ruby 2.7.2p137 …Run Code Online (Sandbox Code Playgroud) 我开发了一个小基准。该基准测试中循环的结果应转换为零,并且下一轮计算应取决于之前循环的零“结果”来测量代码的延迟而不是其吞吐量。将结果移至另一个寄存器并对其本身进行异或运算是行不通的,因为当今的 CPU 认识到与其自身进行异或运算并不依赖于之前的指令。所以我尝试从寄存器本身中减去寄存器,希望CPU(Ryzen Threadripper 3990X)没有像XOR这样的快捷方式。我用一个单独的程序对此进行了评估:
#include <iostream>
#include <chrono>
using namespace std;
using namespace chrono;
int main()
{
auto start = high_resolution_clock::now();
for( size_t i = 1'000'000'000; i--; )
__asm
{
sub eax, eax
sub eax, eax
sub eax, eax
sub eax, eax
sub eax, eax
sub eax, eax
sub eax, eax
sub eax, eax
sub eax, eax
sub eax, eax
}
double ns = (int64_t)duration_cast<nanoseconds>( high_resolution_clock::now() - start ).count() / 10'000'000'000.0;
cout << ns << endl;
}
Run Code Online (Sandbox Code Playgroud)
“不幸的是”CPU在这里也做了一个捷径,每条指令大约需要0.06ns,即。CPU 在每个时钟周期 …