小编Mat*_*ath的帖子

如何快速评估零集?

这个最近的代码高尔夫职位询问了C中快速实现的可能性(假设n是无符号整数):

if (n==6 || n==8 || n==10 || n==12 || n==14 || n==16 || n==18 || n==20)

一种可能的简化是观察数字a[]={6,8,10,12,14,16,18,20}形成算术级数,因此改变范围然后使用一些按位技巧

if (((n - 6) & 14) + 6 == n)

正如John Bollinger 所回答的那样,实现了更短(可能确实更有效)的实现.

现在我问的是什么是类似优雅(并且希望同样有效)的实现

if (n==3 || n==5 || n==11 || n==29 || n==83 || n==245 || n==731 || n==2189)

提示:这次数字a[k]形成几何级数:a[k]=2+3^k.

我想在一般情况下,不能比排序数字更好a[k],然后进行对数搜索以测试是否n是排序数组的成员.

c c++ sorting performance search

22
推荐指数
3
解决办法
1852
查看次数

如何将旧C代码与C++中的保留关键字链接起来?

我有一个10岁以上的C库 - 我相信 - 曾经在过去的好日子里工作得很好,但是当我尝试将它与C++源码(包含主要功能)一起使用时,有一天我遇到了有些困难.

编辑:澄清一下,C库编译得很好gcc,它会生成一个目标文件old_c_library.o.该库认为在某种程度上,这样的C头文件中使用的old_c_library.h#include在D main.cC源文件.然后你的主要C源文件应该编译并与old_c_library.ovia 链接在一起gcc.在这里,我想使用C++源文件main.cpp,并编译/链接它g++.

在编译C++源文件期间发生了以下三个问题:

  1. C库的一个头文件包含C++保留字new(它是一个整数的名称),导致致命错误; 和
  2. C库的一个头文件包含一个calloc调用(缺少显式类型转换),导致致命错误; 和
  3. C库的各种文件包含发生有符号和无符号整数比较的代码,这会导致警告.

编辑:我试图使用#extern "C" { #include "obsolete_c_library.h" }"技巧",如评论中所建议,但这并没有解决我的任何问题.

我可以通过重命名保留字的所有实例并用 - 基本上 - 替换它们来解决问题1.我可以通过类型化calloc调用来解决问题2 .我可能会尝试通过这里建议的想法来解决警告:如何禁用几行代码的GCC警告.

但我仍然想知道,有没有办法以优雅,高层次的方式克服这些困难,而不是真正触及原始图书馆?


相关: C在哪里不是C++的子集?并且不要我投malloc的结果?以及如何使用extern在源文件之间共享变量?.

c c++ portability suppress-warnings

12
推荐指数
1
解决办法
1527
查看次数

解开Knuth的结:如何重组意大利面条代码?

这个问题的灵感来自如何将流程图转换为实现?它询问了从算法上消除goto代码语句的方法.科学论文描述了一般问题的答案.

我已经根据Knuth的算法X 的高级草图实现了一些代码.计算机编程的艺术描述了带有限制前缀词典排列的生成(参见本草案的第16页).

这是上述算法的相应流程图.

这可能是一个非常聪明且非常有效的算法,但代码的结构似乎很难遵循.我最终使用了良好的旧式goto实现:

//Algorithm X;
1:
initialize();
2:
enter_level(k);
3:
set(a[k],q);
if(test() == ok) {
  if (k == n) {
    visit();
    goto 6;
  }
  goto 4;
}
goto 5;
4:
increase(k);
goto 2;
5:
increasev2(a[k]);
if (q != 0) {
  goto 3;
}
6:
decrease(k);
if (k==0) {
  goto 7;
} …
Run Code Online (Sandbox Code Playgroud)

c++ algorithm refactoring loops software-design

10
推荐指数
1
解决办法
453
查看次数

有没有办法_完全_避免缓存未命中?

我在这里阅读了有关缓存如何工作的基础知识:如何以及何时对齐缓存行大小?这里:什么是“缓存友好”代码?,但这些帖子都没有回答我的问题:有没有办法完全在缓存中执行某些代码,即不使用任何对 RAM 的访问(可能超出从 HDD 读取文件的初始过程期间)?据我了解,现在计算的瓶颈主要是内存带宽,“只要在CPU内,就没事”。

有没有办法将程序加载到缓存中,并保留在那里直到程序终止?假设我有一个 1MB 的编译 C 程序,它执行一些科学计算,需要另外 1MB 的内存,并运行 5 天。有没有办法标记此代码,以便它在评估期间不会从缓存中退出?我正在考虑在执行期间给予该代码更高的优先级或类似的优先级。

换句话说,一台空闲的计算机加载其操作系统(例如 Ubuntu),然后什么也不做,使用了多少缓存?空闲时是否存在过多缓存使用?如果操作系统除了执行它之外不执行任何操作,我是否应该期望我的小程序始终位于缓存中?假设 5 分钟后屏幕保护程序启动。这是否会导致大量缓存未命中(从而导​​致性能急剧下降),因为现在它与我的程序竞争缓存空间?我的经验表明,同时运行多个要求不高的程序(例如屏幕保护程序或简单的音频播放器、pdf 阅读器等)不会显着降低我的科学程序的性能,尽管我希望它会始终从缓存中进出。问题是:为什么它的速度不受影响?使用绝对简约的操作系统(如果是的话,那么是哪一个?)来提高(或者更确切地说:维持)计算速度是否有意义?

为了清楚起见,我们可以假设代码非常简单,假设它是一堆嵌套的 for 循环,其中最里面的部分将所有增量变量以 97 为模求和。关键是它足够小,可以放置和执行在缓存中。

c performance caching scientific-computing

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

快速整数矩阵乘法和位旋转黑客

我在问是否可以通过按位运算来改善相当大的整数矩阵乘法。矩阵很小,元素是小的非负整数(small表示最多20个)。

为了使我们专注,我们要非常具体,说我有两个3x3矩阵,它们的整数项0 <= x <15。

以下简单的C ++实现执行了100万次,执行时间约为1s(以linux衡量)time

#include <random>

int main() {
//Random number generator
std::random_device rd;
std::mt19937 eng(rd());
std::uniform_int_distribution<> distr(0, 15);

int A[3][3];
int B[3][3];
int C[3][3];
for (int trials = 0; trials <= 1000000; trials++) {
    //Set up A[] and B[]
    for (int i = 0; i < 3; ++i) {
        for (int j = 0; j < 3; ++j) {
            A[i][j] = distr(eng);
            B[i][j] = distr(eng);
            C[i][j] = 0;
        }
    } …
Run Code Online (Sandbox Code Playgroud)

c++ algorithm performance matrix-multiplication

6
推荐指数
1
解决办法
776
查看次数

如何强制正在运行的程序使用外部手段将其 I/O 缓冲区的内容刷新到磁盘?

我有一个长时间运行的 C 程序,它在开始时打开一个文件,在执行期间写出“有趣”的东西,并在它完成之前关闭文件。使用gcc -o test test.c(gcc version 5.3.1.)编译的代码如下所示:

//contents of test.c
#include<stdio.h>

FILE * filept;

int main() {
    filept = fopen("test.txt","w");
    unsigned long i;
    for (i = 0; i < 1152921504606846976; ++i) {
        if (i == 0) {//This case is interesting!
            fprintf(filept, "Hello world\n");
        }
    }
    fclose(filept);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

问题是,由于这是一种科学计算(想想搜索素数,或者任何你最喜欢的难以破解的东西),它真的可以运行长时间。由于我确定我不够耐心,我想中止当前的计算,但我想以一种智能的方式做到这一点,通过某种方式强制程序通过外部手段清除当前在操作系统中的所有数据缓冲区/磁盘缓存,无论在哪里。

这是我尝试过的(对于上面这个虚假程序,当然不是针对当前仍在运行的真实交易):

  1. 按 ctrl+C; 或者
  2. 发送kill -6 <PID>(以及kill -3 <PID>)——正如@BartekBanachewicz 所建议的,

但是在这些方法中的任何一种之后test.txt,在程序最开始创建的文件 …

c linux io gcc flush

5
推荐指数
1
解决办法
3959
查看次数

如何将流程图转换为实现?

编辑:简介

为了扩大读者群,我通过一个详尽的(有些乏味的)现实生活例子重新阐述了我的原始问题。原始问题显示在下面。

Tom刚被聘为Acme Inc.(根据其前两个工作日的表现)担任初级软件工程师。他的工作是用编程语言Acme ++实现由高级软件开发人员设计的算法。公司按照goto首席执行官的独裁命令执行严格的“不”政策。如果汤姆在试用期内表现出色,他将在公司担任全职工作。

在第1天,Tom收到以下要实施的算法。

Step 1. START
Step 2. Input x
Step 3. In case x<0 goto Step 4 otherwise goto Step 5
Step 4. Set x=-x
Step 5. Output x
Step 6. END
Run Code Online (Sandbox Code Playgroud)

Tom认为任务非常复杂,他认为通过将其表示为流程图,可以从研究程序的抽象结构中受益。在绘制了下图第一天的流程图后,他很快意识到,他被要求计算x的绝对值,并且他可以使用简单的if-then-else语句来实现它。汤姆很高兴,他在一天结束时完成了任务。

在第2天,Tom收到以下要实施的算法。

Step 1. START
Step 2. Input x
Step 3. In case x<0 goto Step 2 otherwise goto Step 4
Step 4. Output x
Step 5. END
Run Code Online (Sandbox Code Playgroud)

作为新手,汤姆再次感到最好还是以抽象的方式理解该算法,因此他绘制了以下流程图第二天的流程图

对流程图的检查表明,Tom被要求执行一个while循环,以等待第一个非负输入。汤姆很高兴,并在一天结束时完成了任务。

基于他出色的表现,汤姆已被公司聘用。

但是,在第3天,汤姆就陷入了深渊,因为他收到了goto由公司前雇员设计的1996年跳高的1000行算法,并且没有其他人知道算法的作用,它是如何做到的,以及为什么首先要以这种方式设计它。但是,这与Tom完全无关,因为他的唯一任务是不管算法是什么都实现该算法。凭借前两天的专业知识,他在具有1997个有向边的1000个节点上绘制了流程图。汤姆非常绝望,他在stackoverflow上询问如何处理这种混乱,有经验的程序员反复建议他这样做。

  1. 将程序分解为较小的部分;和
  2. 他确信在某些情况下实际上可以使用goto; …

compiler-construction algorithm math build-automation

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

包含库的运行时性能成本是多少?

包含整个库(可能有数百个函数)然后只使用单个函数之间是否有任何运行时性能差异:

#include<foo>

int main(int argc, char *argv[]) {
    bar();//from library foo
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

在将相关代码片段从库直接粘贴到代码之间,例如:

void bar() {
...
}

int main(int argc, char *argv[]) {
    bar();//defined just above
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

是什么阻止我在我的C文件开头无意识地包括我最喜欢的(也是最常用的)库?这个流行的线程C/C++:检测多余的#includes?表明编译时间会增加.但编译后的二进制文件会有什么不同吗?第二个项目是否真的胜过第一个项目?


相关:#include <stdio.h>在ac程序中真的做了什么

编辑:这里的问题与相关的不同请问在C/C++中包含未使用的头文件是否有性能损失?这里的问题是包含一个文件.我在这里问,如果包含单个文件与将实际使用的代码片段复制粘贴到源中有任何不同.我稍微调整了标题以反映这种差异.

c c++ performance include

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

报告计算进度的C方式是什么?

这是在C++中使用线程报告计算进度的后续问题.

假设我有一个for执行run_difficult_task()多次的循环,我想推断循环已经推进了多远.我以前写过:

int i;
for (i=0; i < 10000; ++i) {

    run_difficult_task(i);

    if (i % 100 == 0) {
    printf("i = %d\n", i);
    }
}
Run Code Online (Sandbox Code Playgroud)

但这种方法的主要问题是,执行run_difficult_task()可能从字面上永远走(由被卡在一个无限循环等),所以我想获得每一个进展报告k打印出循环变量的值来秒i.

我在这个网站上发现了很多关于面向对象多线程(我并不是很熟悉)的各种编程语言的文献,但我发现用C风格做这个问题看起来已经过时了.有平台无关的C11方式可以做我想要的吗?如果没有,那么我会对使用unix和gcc的方法感兴趣.

注意:我希望run_difficult_task并行运行各种实例(例如,使用OpenMP),但我希望for并行运行循环和报告机制.


相关:如何"多线程"C代码以及如何在普通C中启动线程?

c multithreading pthreads

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

3个顶点上有多少个无向图?

无向图包含3个顶点。可以形成多少个无向图?我尝试了组合公式,但答案错误。

algorithm combinations analysis combinatorics

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

我应该如何摆脱循环?

每当我需要从for(unsigned int i=0;i<bound;++i)C++中的表达式中突破时,我只需设置索引变量i=bound,方法与本答案中描述的相同.我倾向于避免这种break说法,因为老实说,我对它实际上做的事情并不了解.

比较两个说明:

for(unsigned int i=0;i<bound;++i) {
    if (I need a break) {
    break;
    }
}
Run Code Online (Sandbox Code Playgroud)

for(unsigned int i=0;i<bound;++i) {
    if (I need a break) {
    i=bound;
    }
}
Run Code Online (Sandbox Code Playgroud)

我推测第二种方法做一个额外的变量集,然后在i和之间进行一次额外的比较,从性能的角度来看bound,它看起来更昂贵.问题是,打电话break,然后进行这两项测试会更便宜吗?编译的二进制文件是否有所不同?是否存在第二种方法中断的实例,或者我可以安全地选择这两种方法中的任何一种?


相关:`break`是否只适用于`for`,`while`,`do-while`,`switch'和`if`语句?

在没有break语句的情况下突破循环[C]

c c++ performance break

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