我为Project Euler Q14编写了这两个解决方案,在汇编和C++中.它们是用于测试Collatz猜想的相同蛮力方法.装配解决方案与组装
nasm -felf64 p14.asm && gcc p14.o -o p14
Run Code Online (Sandbox Code Playgroud)
C++是用.编译的
g++ p14.cpp -o p14
Run Code Online (Sandbox Code Playgroud)
部件, p14.asm
section .data
fmt db "%d", 10, 0
global main
extern printf
section .text
main:
mov rcx, 1000000
xor rdi, rdi ; max i
xor rsi, rsi ; i
l1:
dec rcx
xor r10, r10 ; count
mov rax, rcx
l2:
test rax, 1
jpe even
mov rbx, 3
mul rbx
inc rax
jmp c1
even:
mov rbx, 2 …Run Code Online (Sandbox Code Playgroud) 我是java的新手,并且昨晚运行了一些代码,这真让我烦恼.我正在构建一个简单的程序来显示for循环中的每个X输出,当我使用模数作为variable % variablevs variable % 5000或诸如此类时,我注意到性能的大幅下降.有人可以向我解释为什么会这样,是什么导致它?所以我可以更好......
这是"高效"代码(对不起,如果我得到一些语法错误我现在不在计算机上的代码)
long startNum = 0;
long stopNum = 1000000000L;
for (long i = startNum; i <= stopNum; i++){
if (i % 50000 == 0) {
System.out.println(i);
}
}
Run Code Online (Sandbox Code Playgroud)
这是"效率低下的代码"
long startNum = 0;
long stopNum = 1000000000L;
long progressCheck = 50000;
for (long i = startNum; i <= stopNum; i++){
if (i % progressCheck == 0) {
System.out.println(i);
}
}
Run Code Online (Sandbox Code Playgroud)
请注意,我有一个日期变量来衡量差异,一旦它变得足够长,第一个花了50毫秒而另一个花了12秒或类似的东西.如果你的电脑比我的电脑更有效,你可能不得不增加stopNum或减少progressCheck.
我在网上找了这个问题,但我找不到答案,也许我只是没有问它.
编辑:我没想到我的问题如此受欢迎,我很欣赏所有答案.我确实在每一半的时间内执行了一个基准测试,效率低下的代码需要相当长的时间,1/4秒与10秒的时间相比.当然他们正在使用println,但他们都做了相同的数量,所以我不认为这会扭曲很多,特别是因为差异是可重复的.至于答案,因为我是Java新手,我会让投票现在决定哪个答案最好.我会在星期三之前选择一个.
EDIT2:我今晚要进行另一次测试,而不是模数,它只是递增一个变量,当它达到progressCheck时,它将执行一次,然后将该变量重置为0.对于第三个选项.
EDIT3.5:
我使用了这段代码,下面我将展示我的结果..谢谢大家的精彩帮助!我也尝试将long的短值与0进行比较,因此我所有的新检查都会发生"65536"次,使其在重复中相等.
public …Run Code Online (Sandbox Code Playgroud) 我有一个128位无符号整数A和一个64位无符号整数B.什么是最快的计算方法A % B- 即将A除以B的(64位)余数?
我希望用C或汇编语言来做这件事,但我需要针对32位x86平台.遗憾的是,我无法利用编译器对128位整数的支持,也无法利用x64架构在单条指令中执行所需操作的能力.
编辑:
谢谢你到目前为止的答案.但是,在我看来,建议的算法会非常慢 - 执行128位到64位除法的最快方法是利用处理器对64位乘32位除法的原生支持吗?有没有人知道是否有办法在一些较小的部门中执行更大的划分?
回复:B多久换一次?
主要是我对一般解决方案感兴趣 - 如果A和B每次都可能不同,你会进行什么计算?
然而,第二种可能的情况是B不会像A那样经常变化 - 每个B可能有多达200个As除以.在这种情况下,你的答案有何不同?
我承认这个问题的答案可能是“一些非常具体的魔法”,但我对在这里观察到的情况感到有点震惊。我想知道是否有人了解这些类型的优化是如何工作的。我发现编译器的设计非常有趣,我真的无法想象它是如何工作的。我确信答案就在 clang 源代码中的某个地方,但我什至不知道该在哪里查找。
我是大学课程的助教,最近有人要求我帮助解决一个简单的家庭作业问题。这让我走上了一条有趣的道路......
问题很简单:在 x86_64 汇编中,编写一个给定(正)整数 n 返回的函数1^2 + 2^2 + 3^2 + ... + n^2。
我决定尝试一下,在帮助他们在 x86_64 汇编中编写此代码后,我(拥有一台 M1 macbook)决定看看是否可以在 arm64 汇编中创建一个不错的解决方案。我想出了一个相对简单直接的解决方案:
_sum_squares:
mov x1, x0 ; Do multiplication from x1
mov x0, xzr ; Clear x0
Lloop:
; x0 <-- (x1 * x1) + x0
madd x0, x1, x1, x0
; Loop until x1 == 0
subs x1, x1, #1
bne Lloop
ret
Run Code Online (Sandbox Code Playgroud)
(我希望有某种很好的方法可以--x1 == 0在一条指令中进行分支,但我想不出任何方法)
注意:任何基础数论课程中都有一个简单的公式,即[n(n + 1)(2n + 1)] / …
显然,x86(可能还有很多其他指令集)将除法运算的商和余数都放在不同的寄存器中.
现在,我们可以信任编译器来优化这样的代码,只使用一次调用来划分:
( x / 6 )
( x % 6 )
Run Code Online (Sandbox Code Playgroud)
他们可能会这样做.仍然,任何语言(或图书馆,但主要是寻找语言)支持同时给出除法和模数结果吗?如果是这样,它们是什么,语法是什么样的?
动态整数将是0到150之间的任何数字.
即 - 数字返回41,需要返回50.如果数字是10则需要返回10.数字是1需要返回10.
如果我将整数修改为小数,我以为我可以使用天花板功能......?然后使用天花板功能,并回到十进制?
唯一的事情也是必须知道这个数字是1,2或3位数(即-7 vs 94 vs 136)
有没有更好的方法来实现这一目标?
谢谢,
是否有可能通过使用纯位加法,减法除以10的无符号整数,也许繁衍?使用资源非常有限且速度慢的处理器.
什么是最快的可分性测试?比如说,给定一个小端架构和一个32位有符号整数:如何计算得非常快,一个数字可被2,3,4,5整除,......最多16?
警告:给定的代码仅为示例.每一行都是独立的!使用模运算的明显解决方案在许多处理器上都很慢,这些处理器没有DIV硬件(像许多ARM一样).有些编译器也无法进行这样的优化(例如,如果divisor是函数的参数或依赖于某些东西).
Divisible_by_1 = do();
Divisible_by_2 = if (!(number & 1)) do();
Divisible_by_3 = ?
Divisible_by_4 = ?
Divisible_by_5 = ?
Divisible_by_6 = ?
Divisible_by_7 = ?
Divisible_by_8 = ?
Divisible_by_9 = ?
Divisible_by_10 = ?
Divisible_by_11 = ?
Divisible_by_12 = ?
Divisible_by_13 = ?
Divisible_by_14 = ?
Divisible_by_15 = ?
Divisible_by_16 = if(!number & 0x0000000F) do();
Run Code Online (Sandbox Code Playgroud)
和特殊情况:
Divisible_by_2k = if(number & (tk-1)) do(); //tk=2**k=(2*2*2*...) k times
Run Code Online (Sandbox Code Playgroud) int x = n / 3; // <-- make this faster
// for instance
int a = n * 3; // <-- normal integer multiplication
int b = (n << 1) + n; // <-- potentially faster multiplication
Run Code Online (Sandbox Code Playgroud)