相关疑难解决方法(0)

为什么GCC在实现整数除法时使用乘以奇数的乘法?

我一直在阅读divmul组装操作,我决定通过在C中编写一个简单的程序来实现它们:

文件分割

#include <stdlib.h>
#include <stdio.h>

int main()
{
    size_t i = 9;
    size_t j = i / 5;
    printf("%zu\n",j);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

然后生成汇编语言代码:

gcc -S division.c -O0 -masm=intel
Run Code Online (Sandbox Code Playgroud)

但是看生成的division.s文件,它不包含任何div操作!相反,它通过位移和魔术数字来做某种黑魔法.这是一个计算代码片段i/5:

mov     rax, QWORD PTR [rbp-16]   ; Move i (=9) to RAX
movabs  rdx, -3689348814741910323 ; Move some magic number to RDX (?)
mul     rdx                       ; Multiply 9 by magic number
mov     rax, rdx                  ; Take only the upper 64 bits of the …
Run Code Online (Sandbox Code Playgroud)

c assembly gcc x86-64 integer-division

206
推荐指数
4
解决办法
1万
查看次数

如何检查整数是偶数还是奇数?

如何在C中检查给定数字是偶数还是奇数?

c integer

193
推荐指数
12
解决办法
36万
查看次数

C++中循环移位(旋转)操作的最佳实践

左右移位运算符(<<和>>)已在C++中可用.但是,我无法找到如何执行循环移位或旋转操作.

如何执行"向左旋转"和"向右旋转"等操作?

在这里向右旋转两次

Initial --> 1000 0011 0100 0010
Run Code Online (Sandbox Code Playgroud)

应该导致:

Final   --> 1010 0000 1101 0000
Run Code Online (Sandbox Code Playgroud)

一个例子会有所帮助.

(编者注:如果旋转计数为零,许多常见的表达方式在C中旋转会受到未定义的行为的影响,或者编译为不止一个旋转机器指令.这个问题的答案应记录最佳实践.)

c c++ bit-manipulation c++-faq rotation

84
推荐指数
9
解决办法
10万
查看次数

使用位移除以10?

是否有可能通过使用纯位加法,减法除以10的无符号整数,也许繁衍?使用资源非常有限且速度慢的处理器.

math bit low-level integer-division micro-optimization

41
推荐指数
4
解决办法
5万
查看次数

检查一个数字是否可以被3整除

我需要找出一个数字是否可以被3整除而不使用%,/或者*.给出的提示是使用atoi()函数.知道怎么做吗?

division modulo integer-division

37
推荐指数
8
解决办法
2万
查看次数

高效的模 255 计算

我试图找到最有效的方法来计算 32 位无符号整数的模 255。我的主要重点是找到一种可以在 x86 和 ARM 平台上运行良好的算法,并着眼于除此之外的适用性。首先,我试图避免内存操作(这可能很昂贵),所以我正在寻找有点复杂的方法,同时避免使用表格。我还试图避免可能昂贵的操作,例如分支和乘法,并尽量减少使用的操作和寄存器的数量。

下面的 ISO-C99 代码捕获了我迄今为止尝试过的八个变体。它包括一个用于详尽测试的框架。我对这个粗略的执行时间测量进行了猛烈抨击,这似乎工作得很好,可以获得第一次性能印象。在一些平台上我试过(全部具有快速整数倍)的变种WARREN_MUL_SHR_2WARREN_MUL_SHR_1DIGIT_SUM_CARRY_OUT_1似乎是最高效的。我的实验表明,我在Compiler Explorer 中尝试的 x86、ARM、PowerPC 和 MIPS 编译都很好地利用了特定于平台的功能,例如三输入LEA、字节扩展指令、乘法累加和指令预测。

该变体NAIVE_USING_DIV使用整数除法,与除数反乘,然后减法。这是基线情况。现代编译器知道如何有效地实现 255 的无符号整数除法(通过乘法),并将在适当的情况下使用离散替换反乘。要计算模数,base-1可以对base数字求和,然后折叠结果。例如3334 mod 9: sum 3+3+3+4 = 13, fold 1+3 = 4. 如果折叠后的结果是base-1,我们需要生成0来代替。DIGIT_SUM_THEN_FOLD使用这种方法。

A. Cockburn,“使用 8/16 位算法有效实现 OSI 传输协议校验和算法”,ACM SIGCOMM 计算机通信评论,卷。17, No. 3, 七月/八月 1987 年,第 13-20 页

展示了base-1在校验和计算模 255 的上下文中有效地添加数字模数的不同方法。计算数字的逐字节总和,并且在每次添加之后,也添加来自加法的任何进位。所以这将是一个ADD a, b …

c algorithm assembly bit-manipulation micro-optimization

21
推荐指数
4
解决办法
577
查看次数

如何检查给定的数字是否能以最快的方式整除15?

处理器中的分区需要很长时间,所以我想问如何以最快的方式检查数字是否可以被其他数字整除,在我的情况下我需要检查数字是否可被15整除.

此外,我一直在浏览网页,并找到有趣的方法来检查数字是否可以被某些数字整除,但我正在寻找快速选项.

注意:由于分工需要很长时间,我正在寻找没有/和的答案%.

c c++ performance integer-division compiler-optimization

17
推荐指数
5
解决办法
3万
查看次数

如何在不使用任何算术运算的情况下找到x mod 15?

假设我们得到一个无符号整数.并且不使用任何算术运算符,+ - / *或者%,我们要找到x mod 15.我们可以使用二进制位操作.

据我所知,我得到了2分.

a = a mod 15 = a mod 16 对于 a<15

让我们a = x mod 15a = x - 15k(对于一些非负k).

a = x - 16k + k......

a mod 16 = ( x mod 16 + k mod 16 ) mod 16

a mod 15 = ( x mod 16 + k mod 16 ) mod 16 …

math bit-manipulation

3
推荐指数
1
解决办法
2449
查看次数

C++ 中哪个更快:mod (%) 还是另一个计数器?

冒着重复的风险,也许我现在找不到类似的帖子:

我正在用 C++(具体来说是 C++20)编写。我有一个带有计数器的循环,每转一次都会进行计数。我们就这样称呼它吧counter。如果counter达到页面限制(我们称之为page_limit),程序应该继续下一页。所以它看起来像这样:

const size_t page_limit = 4942;
size_t counter = 0;
while (counter < foo) {
    if (counter % page_limit == 0) {
        // start new page
    }
    
    // some other code
    counter += 1;
}
Run Code Online (Sandbox Code Playgroud)

现在我想知道,因为计数器变得相当高:如果我不让程序counter % page_limit每次都计算模数,而是创建另一个计数器,程序运行得会更快吗?它可能看起来像这样:

const size_t page_limit = 4942;
size_t counter = 0;
size_t page_counter = 4942;
while (counter < foo) {
    if (page_counter == page_limit) {
        // start new page
        page_counter = 0;
    } …
Run Code Online (Sandbox Code Playgroud)

c++ performance assembly micro-optimization branch-prediction

2
推荐指数
1
解决办法
859
查看次数

优化的可被整除

假设我有数字 X,我想看看它是否可以被 Y 整除。最优化的方法是什么?

到目前为止,我有:

int X = 12;
int Y = 4;
(X ^ Y) & 0b111 ==0    # Check if X XOR Y (mask size Y) == 0
Run Code Online (Sandbox Code Playgroud)

虽然我是硬编码0b111(Y 的掩码大小)。顺便说一句,我不关心语言,我只是用 C 标记它。


顺便说一句,使用编译器资源管理器我得到:

int is_divisible_by(int x, int y) {
    return x % y == 0;
};
Run Code Online (Sandbox Code Playgroud)
# -O3
is_divisible_by:
        movl    %edi, %eax
        cltd
        idivl   %esi         # seems to just be doing straight division?
        xorl    %eax, %eax
        testl   %edx, %edx
        sete    %al
        ret
Run Code Online (Sandbox Code Playgroud)

c optimization x86 assembly bit-manipulation

0
推荐指数
1
解决办法
118
查看次数