相关疑难解决方法(0)

为什么处理排序数组比处理未排序数组更快?

这是一段看似非常特殊的C++代码.出于某种奇怪的原因,奇迹般地对数据进行排序使得代码几乎快了六倍.

#include <algorithm>
#include <ctime>
#include <iostream>

int main()
{
    // Generate data
    const unsigned arraySize = 32768;
    int data[arraySize];

    for (unsigned c = 0; c < arraySize; ++c)
        data[c] = std::rand() % 256;

    // !!! With this, the next loop runs faster.
    std::sort(data, data + arraySize);

    // Test
    clock_t start = clock();
    long long sum = 0;

    for (unsigned i = 0; i < 100000; ++i)
    {
        // Primary loop
        for (unsigned c = 0; c < arraySize; ++c) …
Run Code Online (Sandbox Code Playgroud)

c++ java optimization performance branch-prediction

2万
推荐指数
27
解决办法
142万
查看次数

用于测试Collat​​z猜想的C++代码比手写程序集更快 - 为什么?

我为Project Euler Q14编写了这两个解决方案,在汇编和C++中.它们是用于测试Collat​​z猜想的相同蛮力方法.装配解决方案与组装

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)

c++ optimization performance x86 assembly

803
推荐指数
8
解决办法
14万
查看次数

哪个更快:while(1)或while(2)?

这是一位高级经理提出的面试问题.

哪个更快?

while(1) {
    // Some code
}
Run Code Online (Sandbox Code Playgroud)

要么

while(2) {
    //Some code
}
Run Code Online (Sandbox Code Playgroud)

我说两者都有相同的执行速度,因为里面的表达式while应该最终评估为truefalse.在这种情况下,两者都评估,true并且条件内没有额外的条件指令while.因此,两者都具有相同的执行速度,而我更喜欢(1).

但采访者自信地说:"检查你的基础知识.while(1)比快while(2)." (他没有测试我的信心)

这是真的?

另请参阅:"for(;;)"是否比"while(TRUE)"快?如果没有,为什么人们会使用它?

c performance while-loop

582
推荐指数
15
解决办法
9万
查看次数

使用 -O3 进行冒泡排序比使用 GCC 的 -O2 慢

我用 C 语言实现了一个冒泡排序,并在测试其性能时发现该-O3标志使其运行速度甚至比没有标志时还要慢!与此同时-O2,它的运行速度比预期的要快得多。

没有优化:

time ./sort 30000

./sort 30000  1.82s user 0.00s system 99% cpu 1.816 total
Run Code Online (Sandbox Code Playgroud)

-O2

time ./sort 30000

./sort 30000  1.00s user 0.00s system 99% cpu 1.005 total
Run Code Online (Sandbox Code Playgroud)

-O3

time ./sort 30000

./sort 30000  2.01s user 0.00s system 99% cpu 2.007 total
Run Code Online (Sandbox Code Playgroud)

代码:

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

int n;

void bubblesort(int *buf)
{
    bool changed = true;
    for (int i = n; changed == true; …
Run Code Online (Sandbox Code Playgroud)

c gcc x86-64 cpu-architecture compiler-optimization

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

为什么定义数组之外的第一个元素默认为零?

我正在准备 C++ 入门课程的期末考试。我们的教授给了我们这个问题来练习:

解释为什么代码会产生以下输出:120 200 16 0

using namespace std;
int main()
{
  int x[] = {120, 200, 16};
  for (int i = 0; i < 4; i++)
    cout << x[i] << " ";
}
Run Code Online (Sandbox Code Playgroud)

该问题的示例答案是:

cout 语句只是循环遍历其下标由 for 循环的增量定义的数组元素。元素大小不是由数组初始化定义的。for 循环定义了数组的大小,该大小恰好超出了初始化元素的数量,因此最后一个元素默认为零。第一个 for 循环打印元素 0 (120),第二个循环打印元素 1 (200),第三个循环打印元素 2 (16),第四个循环打印默认数组值零,因为元素 3 没有任何初始化。现在 i 点超出了条件并且 for 循环终止。

我有点困惑为什么数组之外的最后一个元素总是“默认”为零。为了进行实验,我将问题中的代码粘贴到我的 IDE 中,但将 for 循环更改为for (int i = 0; i < 8; i++). 然后输出更改为120 200 16 0 4196320 0 …

c++ arrays initialization undefined-behavior zero-initialization

92
推荐指数
5
解决办法
6656
查看次数

与C++中的普通指针相比,智能指针的开销是多少?

与C++ 11中的普通指针相比,智能指针的开销是多少?换句话说,如果我使用智能指针,我的代码会变慢吗?如果是这样,速度会慢多少?

具体来说,我问的是C++ 11 std::shared_ptrstd::unique_ptr.

显然,推下堆栈的东西会变得更大(至少我认为是这样),因为智能指针也需要存储其内部状态(引用计数等),问题是,这是多少影响我的表现,如果有的话?

例如,我从函数而不是普通指针返回一个智能指针:

std::shared_ptr<const Value> getValue();
// versus
const Value *getValue();
Run Code Online (Sandbox Code Playgroud)

或者,例如,当我的一个函数接受智能指针作为参数而不是普通指针时:

void setValue(std::shared_ptr<const Value> val);
// versus
void setValue(const Value *val);
Run Code Online (Sandbox Code Playgroud)

c++ performance smart-pointers c++11

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

如何从GCC /铿锵声组件输出中消除"噪音"?

我想检查boost::variant在我的代码中应用的程序集输出,以便查看哪些中间调用被优化掉了.

当我编译以下示例(使用GCC 5.3 g++ -O3 -std=c++14 -S)时,似乎编译器优化了所有内容并直接返回100:

(...)
main:
.LFB9320:
    .cfi_startproc
    movl    $100, %eax
    ret
    .cfi_endproc
(...)
Run Code Online (Sandbox Code Playgroud)
#include <boost/variant.hpp>

struct Foo
{
    int get() { return 100; }
};

struct Bar
{
    int get() { return 999; }
};

using Variant = boost::variant<Foo, Bar>;


int run(Variant v)
{
    return boost::apply_visitor([](auto& x){return x.get();}, v);
}
int main()
{
    Foo f;
    return run(f);
}
Run Code Online (Sandbox Code Playgroud)

但是,完整的程序集输出包含的内容远远超过上面的摘录,对我而言,它看起来永远不会被调用.有没有办法告诉GCC/clang删除所有"噪音"并输出程序运行时实际调用的内容?


完整装配输出:

    .file   "main1.cpp"
    .section    .rodata.str1.8,"aMS",@progbits,1
    .align 8
.LC0:
    .string "/opt/boost/include/boost/variant/detail/forced_return.hpp"
    .section    .rodata.str1.1,"aMS",@progbits,1
.LC1: …
Run Code Online (Sandbox Code Playgroud)

c++ assembly gcc clang

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

当指定-g时gcc是否定义了什么?

不久,我想知道gcc(或g ++.我需要它在C中,但也很好奇c ++)定义任何特殊符号如果-g启用.可以?如果是这样,有什么符号?

在搜索过程中,我发现:

  • _DEBUG是手动定义的(通过手动我的意思-D_DEBUG)并且是从Visual C程序员那里习惯的习惯(因为VC _DEBUG在调试模式下编译时定义)
  • NDEBUG如果不在调试模式下,则定义.虽然我发现有几个地方在说这个,但是我在.c和.cpp文件中尝试使用我的gcc和g ++,并且在-g没有这些符号的情况下都没有定义这样的符号!

编辑:让我演示为什么我不想使用非标准符号:

想象一下内核模块做了什么,并提供了包含在其他内核模块中的头文件,以便它们可以连接到这个.

现在作为一个工具,我在其中一个头文件中:

#ifdef DEBUG <-- This is what I need
#define LOG(x, ...) printk("Some extra info"x, ##__VA_ARGS__);
#else
#define LOG(x, ...) printk("Without extra info"x, ##__VA_ARGS__);
#endif
Run Code Online (Sandbox Code Playgroud)

请注意,名称不是真的LOG,这是一个例子.

现在,我可以为DEBUG自己使用任何符号,但如果有人包含我的标题,他们可能无法定义该符号.当然,我可以告诉他们"顺便说一句,在调试模式中获取标题,定义另一个符号",但这对我来说听起来不对.

我可以在标头中定义符号并将其包含在所有头文件中.这样,如果它们包含我的一个标题,它们也会得到调试符号.现在的问题是,如果他们希望在调试模式下进行编译,我的头仍然认为他们是在调试模式.

所以我认为最好的是使用在使用时定义的符号-g,如果有的话!

更新

到目前为止,我得出结论,我可以这样做:

how_to_build.h

#if !defined(NDEBUG)
#define MY_DEBUG
#endif
Run Code Online (Sandbox Code Playgroud)

用法:

#include "how_to_build.h"

#ifdef MY_DEBUG
// rest of the story
Run Code Online (Sandbox Code Playgroud)

这样,通用选项也NDEBUG …

c debugging gcc c-preprocessor

45
推荐指数
3
解决办法
2万
查看次数

整数乘法与现代CPU上的加法速度完全相同

我经常听到这种说法,现代硬件上的乘法是如此优化,以至于它实际上与加法相同.真的吗?

我从来没有得到任何权威的确认.我自己的研究只会增加问题.速度测试通常会显示让我感到困惑的数据.这是一个例子:

#include <stdio.h>
#include <sys/time.h>

unsigned int time1000() {
    timeval val;
    gettimeofday(&val, 0);
    val.tv_sec &= 0xffff;
    return val.tv_sec * 1000 + val.tv_usec / 1000;
}

int main() {
    unsigned int sum = 1, T = time1000();
    for (int i = 1; i < 100000000; i++) {
        sum += i + (i+1); sum++;
    }
    printf("%u %u\n", time1000() - T, sum);
    sum = 1;
    T = time1000();
    for (int i = 1; i < 100000000; i++) {
        sum += i * …
Run Code Online (Sandbox Code Playgroud)

c++ cpu performance multiplication addition

39
推荐指数
6
解决办法
2万
查看次数

为什么不总是使用编译器优化?

我前面问过的一个问题是未定义的行为,因此编译器优化实际上导致程序中断.

但是如果代码中没有未定义的行为,那么有没有理由不使用编译器优化?我理解有时候,出于调试目的,可能不需要优化代码(如果我错了请纠正我).除此之外,在生产代码上,为什么不总是使用编译器优化?

另外,是否有理由使用,-O而不是-O2-O3

compiler-construction compiler-optimization

33
推荐指数
3
解决办法
9929
查看次数