micro-optimization 相关问题

微优化是对小部分代码进行细致调整的过程,以解决其操作的某些方面(内存使用过多,性能不佳等)的感知缺陷。

为什么“if x is None: pass”比单独的“x is None”更快?

Python 3.12 中的计时结果(与不同机器上的 3.11 和 3.13 类似): 当 x = 无时: 13.8 ns x 无 10.1 ns 如果 x 为 None:通过 当 x = True 时: 13.9 ns x 无 11.1 ns,如果 x 为

回答 1 投票 0

在 32 位处理器上优化了 53->32 位模计算

当我在不支持或缓慢支持双重计算的 32 位处理器上研究 MRG32k3a PRNG 的高效实现时,出现了这个问题。我对ARM特别感兴趣,...

回答 1 投票 0

使用AVX2是否可以实现对字数组上LZCNT的更快处理?

我需要使用 LZCNT 进行反向位扫描,字数组:16 位。 在 Intel 最新一代处理器上,LZCNT 的吞吐量为每个时钟执行 1 次。 AMD Ryzen 的吞吐量似乎...

回答 2 投票 0

如何通过 ID 而不是字符串名称来 g_signal_connect() ?

GTK 中处理按钮按下的典型方法是: g_signal_connect(GTK_BUTTON(myButton), "按下", G_CALLBACK(myButtonHandler), NULL); 然而,我发现它很糟糕,很慢,而且没有必要......

回答 1 投票 0

LEA 与 MOV imm64 将地址常量加载到寄存器中

我有一个常量(64 位)地址,我想将其加载到寄存器中。该地址位于代码段中,因此可以相对于RIP 进行寻址。两者有什么区别 移动...

回答 2 投票 0

循环内if(循环不变)if语句的编译器优化

我在C中有一个这样的函数(在伪代码中,删除不重要的部分): int func(int s, int x, int* a, int* r) { 整数我; // 做一些事情 对于 (i=0;i 我在 C 中有一个这样的函数(在伪代码中,删除了不重要的部分): int func(int s, int x, int* a, int* r) { int i; // do some stuff for (i=0;i<a_really_big_int;++i) { if (s) r[i] = x ^ i; else r[i] = x ^ a[i]; // and maybe a couple other ways of computing r // that are equally fast individually } // do some other stuff } 这段代码被调用得太多,以至于这个循环实际上是代码中的速度瓶颈。我想知道一些事情: 由于 switch s 是函数中的常量,好的编译器会优化循环以使分支不会一直减慢速度吗? 如果没有,有什么好的方法来优化这段代码? ==== 这是包含更完整示例的更新: int func(int s, int start,int stop,int stride, double *x,double *b, int *a,int *flips,int *signs,int i_max, double *c) { int i,k,st; for (k=start; k<stop; k += stride) { b[k] = 0; for (i=0;i<i_max;++i) { /* this is the code in question */ if (s) st = k^flips[i]; else st = a[k]^flips[i]; /* done with code in question */ b[k] += x[st] * (__builtin_popcount(st & signs[i])%2 ? -c[i] : c[i]); } } } 编辑2: 如果有人好奇,我最终重构了代码并将整个内部 for 循环(带有 i_max)提升到外面,使 really_big_int 循环变得更加简单,并且希望易于矢量化! (并且还避免无数次执行一堆额外的逻辑) 优化代码的一个明显方法是将条件拉到循环之外: if (s) for (i=0;i<a_really_big_int;++i) { r[i] = x ^ i; } else for (i=0;i<a_really_big_int;++i) { r[i] = x ^ a[i]; } 精明的编译器也许能够将其更改为一次多个元素的 r[] 赋值。 微观优化 通常不值得花时间——审查更大的问题更有效。 然而,要进行微观优化,尝试各种方法,然后对它们进行分析以找到最好的方法,可以做出适度的改进。 除了 @wallyk 和 @kabanus 好的答案之外,一些简单的编译器还受益于以 0 结尾的循环。 // for (i=0;i<a_really_big_int;++i) { for (i=a_really_big_int; --i; ) { [编辑第二次优化] OP 添加了一个更完整的示例。问题之一是编译器无法假设 b 指向的内存与其他内存不重叠。这会阻止某些优化。 假设它们实际上不重叠,请在 restrict 上使用 b 来允许优化。 const 对于无法推断出这一点的较弱编译器也有帮助。 restrict 如果参考数据不重叠,其他人也可能受益。 // int func(int s, int start, int stop, int stride, double *x, // double *b, int *a, int *flips, // int *signs, int i_max, double *c) { int func(int s, int start, int stop, int stride, const double * restrict x, double * restrict b, const int * restrict a, const int * restrict flips, const int * restrict signs, int i_max, double *c) { 您的所有命令都是循环中的快速 O(1) 命令。 if 绝对是经过优化的,如果您的所有命令都是 r[i]=somethingquick 形式,那么您的 for+if 也是如此。您的问题可能归结为 big int 可以有多小? 快速 int main 从 INT_MIN 到 INT_MAX 求和为一个长变量,在 Windows 上的 Ubuntu 子系统上对我来说大约需要 10 秒。您的命令可能会将其乘以几倍,很快就会达到一分钟。最重要的是,如果您确实进行了大量迭代,这可能是无法避免的。 如果 r[i] 是独立计算的,这将是线程/多处理的经典用法。 编辑: 我认为 % 无论如何都会被编译器优化,但如果没有,请注意 x & 1 对于奇数/偶数检查要快得多。 假设x86_64,您可以确保指针对齐到16字节并使用intrinsics。如果它仅在具有 AVX2 的系统上运行,您可以使用 __mm256 变体(与 avx512* 类似) int func(int s, int x, const __m128i* restrict a, __m128i* restrict r) { size_t i = 0, max = a_really_big_int / 4; __m128i xv = _mm_set1_epi32(x); // do some stuff if (s) { __m128i iv = _mm_set_epi32(3,2,1,0); //or is it 0,1,2,3? __m128i four = _mm_set1_epi32(4); for ( ;i<max; ++i, iv=_mm_add_epi32(iv,four)) { r[i] = _mm_xor_si128(xv,iv); } }else{ /*not (s)*/ for (;i<max;++i){ r[i] = _mm_xor_si128(xv,a[i]); } } // do some other stuff } 虽然 if 语句将在任何像样的编译器上进行优化(除非你要求编译器不要优化),但我会考虑将优化写入(以防万一你在没有优化的情况下编译)。 此外,虽然编译器可能会优化“绝对”if语句,但我会考虑手动优化它,要么使用任何可用的内置函数,要么使用按位操作。 即 b[k] += x[st] * ( ((__builtin_popcount(st & signs[I]) & 1) * ((int)0xFFFFFFFFFFFFFFFF)) ^c[I] ); 这将取 popcount 的最后一位(1 == 奇数,0 == 偶数),将其乘以常量(如果是奇数则所有位为 1,如果为真则所有位为 0),然后对 c[I] 值进行异或(与 0-c[I] 或 ~(c[I]) 相同。 这将避免在第二个 absolute if 语句未优化的情况下发生指令跳转。 附注 我使用了一个 8 字节长的值,并通过将其转换为 int 来截断其长度。这是因为我不知道 int 在您的系统上可能有多长(在我的系统上是 4 个字节,即 0xFFFFFFFF)。

回答 5 投票 0

将变量或参数打包到结构/联合中会带来不可预见的性能损失吗?

这不是询问结构填充/打包,它是指出于对齐目的插入到结构中的任何未命名字节。 我有这个功能: #包括 uint8_t get_in...

回答 1 投票 0

控制类成员布局和析构函数顺序

我的班级有两名成员。 C类{ 类型A; B型b; }; 假设没有继承。对于这门课,我担心三件事。

回答 1 投票 0

JavaScript:`if / else`语句比条件语句更快吗?

考虑以下两段代码: var adj=0>grip.y?0 0) 调整 = 0; 否则...

回答 3 投票 0

如何在 C 中执行无分支条件算术运算?

我有一个值 int x,我想有条件地向其中添加(例如)一个值 int y,具体取决于 bool c。我可以写这样的代码: 如果(三) x+=y; 没有分支我怎么能写这个?

回答 1 投票 0

llvm-bolt 仪器模式是否会导致 BOLT 轮廓不太准确?

BOLT 二进制优化器建议使用 perf 来分析二进制文件以进行优化。但是,如果“性能不可用”,它们有一个 llvm-bolt 模式,也可以分析应用程序...

回答 1 投票 0

int、unsigned int、uint_fastN_t 和 int_fastN_t 的优缺点是什么?

我有一个变量,类型并不重要;可能的范围很容易适合上述任何类型。例如循环计数器。 ETC。 使用的优点和缺点是什么: 整数 不……

回答 1 投票 0

为什么在此示例中使用 [[unlikely]] 属性?

我正在阅读https://iq.opengenus.org/cpp-likely-and-unlikely-attributes/,我不理解/同意一些事情。 在下面的代码中: void doModulus( 向量 &vec , int mod...

回答 1 投票 0

WASM 指令成本

我有一个应用程序需要可插入模块来实现从一个字节数组到另一个字节数组的任意函数。一些功能可能是计算密集型的。

回答 0 投票 0

加权 popcount 集合/集合位的总和索引

你知道任何聪明的方法来总结所有设置位的索引吗? 我知道代码 / 设置位索引的总和 int A073642(uint64_t n) { 返回 __popcnt64(n & 0xAAAAAAAAAAAAAAAA) + (__popcnt6...

回答 1 投票 0

是否可以在C中一次获得无符号商和余数?

我已经看到这个关于在 C 中的单个操作中获取商和余数的问题。但是 C div 和 ldiv 函数采用 int 和 long 参数。但是我怎样才能执行未签名的除法...

回答 1 投票 0

x86-64 指令与直到零?

我知道有一条指令会重复(比如repnz)。我有一个情况,我有一个(8 位)数组,它是 [7, 2, 3, 4, ..., 7, 0, 0, 0 ...](我最后有 64 个字节的零)。我想要...

回答 0 投票 0

我怎么能为这个函数做循环展开? [关闭]

我正在尝试使用并行累加器进行循环展开,但我对依赖项和计算感到困惑。 result 和 result2 理想情况下应该相互独立运行,以便 ...

回答 0 投票 0

不确定AMD Zen 3架构(功能单元、指令发布时间/延迟)

我正在尝试查找有关 AMD 处理器 zen 3 架构的整数和浮点功能单元的信息。以及整数和fl的发布时间和延迟...

回答 0 投票 0

优化嵌套循环的模式填充数组,帮助编译器产生高效的ARM汇编?

我刚刚接到一项任务,要求重写以下C函数,以帮助ARM编译器生成更高效的汇编代码。有谁知道怎么做? void some_function(int *data)...。

回答 1 投票 1

© www.soinside.com 2019 - 2024. All rights reserved.