我想(x + y)/2用Java 计算任意两个整数x,y的方法.如果x + y> Integer.MAX_VALUE或<Integer.MIN_VALUE,则天真的方式会遇到问题.
番石榴IntMath 使用这种技术:
public static int mean(int x, int y) {
// Efficient method for computing the arithmetic mean.
// The alternative (x + y) / 2 fails for large values.
// The alternative (x + y) >>> 1 fails for negative values.
return (x & y) + ((x ^ y) >> 1);
}
Run Code Online (Sandbox Code Playgroud)
...但是这会向负无穷大方向发展,这意味着例程与{-1,-2}等值的天真方式不一致(给-2而不是-1).
是否有任何相应的例程向0截断?
"只是使用long"不是我正在寻找的答案,因为我想要一种适用于长输入的方法.BigInteger也不是我正在寻找的答案.我不想要任何分支机构的解决方案.
除了其他方面,x86-64 SysV ABI指定了如何在寄存器中传递函数参数(第一个参数in rdi,then rsi等等),以及如何传回整数返回值(in rax和then rdx表示非常大的值).
然而,我找不到的是当传递小于64位的类型时,参数或返回值寄存器的高位应该是什么.
例如,对于以下功能:
void foo(unsigned x, unsigned y);
Run Code Online (Sandbox Code Playgroud)
... x将被传入rdi和y在rsi,但他们只是32位.不要的高32位rdi和rsi必须为零?直观地说,我会假设是,但是所有gcc,clang和icc 生成的代码mov在开始时都有特定的指令将高位清零,所以看起来编译器假定不然.
类似地,编译器似乎假设rax如果返回值小于64 位,则返回值的高位可能具有垃圾位.例如,以下代码中的循环:
unsigned gives32();
unsigned short gives16();
long sum32_64() {
long total = 0;
for (int i=1000; i--; ) {
total += gives32();
}
return total;
}
long sum16_64() {
long total = 0;
for (int i=1000; i--; ) {
total += …Run Code Online (Sandbox Code Playgroud) 在-XX:+PrintCompilation最近使用(JDK 8r111)来检查方法编译时,我注意到一个新列,它没有出现在我可以在该主题上找到的文档中:
this column
|
|
v
600 1 s 3 java.util.Hashtable::get (69 bytes)
601 4 3 java.lang.Character::toLowerCase (6 bytes)
601 8 3 java.io.UnixFileSystem::normalize (75 bytes)
602 12 3 java.lang.ThreadLocal::get (38 bytes)
602 14 3 java.lang.ThreadLocal$ThreadLocalMap::getEntry (42 bytes)
602 18 2 java.lang.String::startsWith (72 bytes)
602 10 4 java.lang.String::equals (81 bytes)
602 2 % 4 java.lang.String::hashCode @ 24 (55 bytes)
602 16 s! 3 sun.misc.URLClassPath::getLoader (197 bytes)
603 23 n 0 java.lang.System::arraycopy (native) (static)
604 …Run Code Online (Sandbox Code Playgroud) 我读了一篇有趣的论文,名为"对最后一级缓存的高分辨率侧通道攻击",并希望找到我自己机器的索引哈希函数 - 即Intel Core i7-7500U(Kaby Lake架构) - 遵循这项工作的线索.
为了对散列函数进行逆向工程,本文提到了第一步:
for (n=16; ; n++)
{
// ignore any miss on first run
for (fill=0; !fill; fill++)
{
// set pmc to count LLC miss
reset_pmc();
for (a=0; a<n; a++)
// set_count*line_size=2^19
load(a*2^19);
}
// get the LLC miss count
if (read_pmc()>0)
{
min = n;
break;
}
}
Run Code Online (Sandbox Code Playgroud)
我如何编写代码reset_pmc(),并read_pmc()在C++?从我到目前为止在线阅读的所有内容来看,我认为它需要内联汇编代码,但我不知道用什么指令来获取LLC未命中数.如果有人可以为这两个步骤指定代码,我将不得不承担责任.
我在VMware工作站上运行Ubuntu 16.04.1(64位).
PS:我发现这些记载LONGEST_LAT_CACHE.REFERENCES并LONGEST_LAT_CACHE.MISSES在第18的的3B卷英特尔架构软件开发手册,但我不知道如何使用它们.
采用这个简单的函数,在由std::mutex以下实现的锁定下递增整数:
#include <mutex>
std::mutex m;
void inc(int& i) {
std::unique_lock<std::mutex> lock(m);
i++;
}
Run Code Online (Sandbox Code Playgroud)
我希望这(在内联之后)以直接的方式编译,然后调用m.lock()增量.im.unlock()
检查生成的程序集的最新版本的gcc和clang,但是,我们看到一个额外的并发症.gcc首先考虑版本:
inc(int&):
mov eax, OFFSET FLAT:__gthrw___pthread_key_create(unsigned int*, void (*)(void*))
test rax, rax
je .L2
push rbx
mov rbx, rdi
mov edi, OFFSET FLAT:m
call __gthrw_pthread_mutex_lock(pthread_mutex_t*)
test eax, eax
jne .L10
add DWORD PTR [rbx], 1
mov edi, OFFSET FLAT:m
pop rbx
jmp __gthrw_pthread_mutex_unlock(pthread_mutex_t*)
.L2:
add DWORD PTR [rdi], 1
ret
.L10:
mov edi, eax …Run Code Online (Sandbox Code Playgroud) 我使用Instrument的时间分析器来描述我的代码,并放大到反汇编,这里是结果的片段:
我不希望一条mov指令占23.3%的时间,而div指令几乎什么也没做.这让我相信这些结果是不可靠的.这是真的吗?或者我只是遇到了仪器错误?或者我是否需要使用一些选项来获得可靠的结果?
这个问题是否有任何参考?
特别是,允许不同函数中两个自动变量的地址比较如下:
sink.c
#include <stdio.h>
#include <stdlib.h>
void sink(void *l, void *r) {
puts(l == r ? "equal" : "not equal");
exit(0);
}
Run Code Online (Sandbox Code Playgroud)
main.c中
typedef struct { char x[32]; } Foo;
void sink(void *l, void *r);
Foo make(void *p) {
Foo f2;
sink(&f2, p);
return f2;
}
int main() {
Foo f1 = make(&f1);
}
Run Code Online (Sandbox Code Playgroud)
我希望它可以打印not equal的f1和f2是不同的对象.使用gcc我得到了not equal,但是使用我的本地版本的clang 3.8 1,它在打印equal时编译为clang -O1 sink.c main.c2.
拆卸make和main …
考虑您要计算64位和128位无符号数乘以结果的低128位,并且您可用的最大乘法是C类64位乘法,它需要两个64位无符号输入并返回结果的低64位.
需要多少次乘法?
当然你可以用8来做:将所有输入分解为32位块并使用64位乘法来进行4*2 = 8所需的全宽32*32-> 64乘法,但是可以做得更好?
当然,算法应该在乘法之上仅进行"合理"数量的加法或其他基本算术(我对重新发明乘法作为加法循环并因此声称"零"乘法的解决方案不感兴趣).
我有一个带有几个子模块的git项目(回想起来我有点后悔的选择).它使用gnumake
目前,我希望人们在第一次构建项目之前手动发布git submodule update --init1,并且在提取任何更新子模块引用的更改之后.
但是,我希望Makefile在需要时自动发出这些命令.如果他们有时在不需要时发出命令(虚假更新),这是可以的 - 但它不应该经常发生.
对于初始init,似乎有足够的规则(对于存在于目录中的子模块module1:
module1/.git:
git submodule update --init
Run Code Online (Sandbox Code Playgroud)
在这里选择.git作为"表示"子模块的文件是相当随意的,它可能是一些其他文件.
但是,在更新引用时更新子模块效果不佳.我想我可以让子模块依赖于根.gitmodules文件,我想在子模块引用更新时应该更改,例如:
module1/.git: .gitmodules
git submodule update --init
Run Code Online (Sandbox Code Playgroud)
这里使用.git似乎是错误的:可能是在update运行时不一定直接更新(特别是如果没有更新此特定子模块),这将使更新命令每次都运行.
在这里寻找更清洁的解决方案.
1或者可能--recursive在初始化上使用参数clone,这具有相同的效果.
假设我正在实现一个集合,例如std::vector。我需要实现iterator和const_iterator,但是一旦完成,iterator就const_iterator不能仅实现为iterator<const T>(T集合中的类型在哪里)?
一定有原因为什么它不起作用,因为有上百万个问题有关如何在实现时重用代码iterator,const_iterator但是没有一个说“仅const T作为类型使用”。