Tagged: C++ Toggle Comment Threads | 键盘快捷键

  • jinzihao pm10:23 on 2017年7月4日 链接地址 | 回复
    Tags: C++   

    (待填充)
    fifo文件的使用与mkfifo命令
    C语言的getopt函数
    getenv函数
    stringification macro
    -fno-function-cse
    -finstrument-functions

     
  • jinzihao pm11:55 on 2017年6月11日 链接地址 | 回复
    Tags: AI, C++, 人工智能, 围棋   

    围棋AI 

    (这个坑出分后填上…)

     
  • jinzihao pm3:37 on 2017年3月1日 链接地址 | 回复
    Tags: C++   

    static struct gatedesc idt[256] = {{0}};
    

    这行代码看起来有点奇怪…
    其实struct也可以用{value1, value2, …}的方式初始化,与数组的初始化类似,例如:

    struct gatedesc idt1 = {7};
    

    表示idt1的第一个元素用7初始化,其余元素用0初始化。
    因此开始这行代码表示新建一个大小为256的gatedesc数组,数组的每一项的每个元素(或说“成员变量”)都是0。

     
  • jinzihao pm2:46 on 2017年3月1日 链接地址 | 回复
    Tags: C++, x86   

    C语言struct定义中的冒号(“:”) 

    在C语言的struct定义中,可以使用冒号(“:”)来指定struct中的元素所占的bit数,注意是bit不是byte,因此可以出现诸如3bit、11bit的元素,如下面这段代码所示:

    struct gatedesc {
        unsigned gd_off_15_0 : 16;        // low 16 bits of offset in segment
        unsigned gd_ss : 16;            // segment selector
        unsigned gd_args : 5;            // # args, 0 for interrupt/trap gates
        unsigned gd_rsv1 : 3;            // reserved(should be zero I guess)
        unsigned gd_type : 4;            // type(STS_{TG,IG32,TG32})
        unsigned gd_s : 1;                // must be 0 (system)
        unsigned gd_dpl : 2;            // descriptor(meaning new) privilege level
        unsigned gd_p : 1;                // Present
        unsigned gd_off_31_16 : 16;        // high bits of offset in segment
    };

    这个数据结构对应于如下两种x86架构下的中断描述符(IDT):

    这种语法在表示一些带有非整字节元素的数据结构时非常方便,例如x86架构定义的一些数据结构,或是类似IPv4的网络协议头,可以免于用C++的成员函数的方式来封装。

     
  • jinzihao pm6:33 on 2016年8月29日 链接地址 | 回复
    Tags: C++,   

    C语言判断奇偶性:i&1和i%2 

    三个月前的一篇文章中,曾经好奇为什么C语言中同样是判断整数奇偶性,在不开编译优化(gcc -O0)的情况下,

    (1) bool isOdd = i & 1;

    (2) bool isOdd = i % 2;

    略快(但并没有快很多)。

    看过反汇编得到的汇编代码,发现即便没有开编译优化选项,编译器对于(2)也没有使用除法指令idiv,从而避免了(2)比(1)慢得多的情况。编译器由(2)编译出的汇编代码的作用,是保存一个临时变量t,如果需要判断奇偶性的数i是正数,则t取0,否则t取1;“i是否为奇数”则可以表示为((i + t) & 1) – t,这样就会比i & 1稍慢(但不会慢很多)。

    实际上(1)对于i为负数的情况会得到错误的结果,因此(2)的一点点额外的时间开销是完全有必要的;如果将上一篇文章main函数里面的int全部改为unsigned int,即使在指定gcc -O0的情况下,编译器也会对(1)和(2)编译出完全相同的汇编代码,即(2)也会被优化为i & 1。

     

     
    • 陈文 下午3:25 on 2016年9月9日 链接地址 | 回复

      你的网站用teleport下载文件只有60k/s,很多文件下载半天也下载不下来

    • 陈文 下午3:26 on 2016年9月9日 链接地址 | 回复

      另外问一下,这个网页http://netmite.com/android/srv/2.0/getapk.php的小玩意怎么放在我的网站上运行

  • jinzihao pm11:32 on 2016年5月19日 链接地址 | 回复
    Tags: C++   

    今天写C++代码时遇到需要频繁判断奇偶性的问题。最合乎直觉的做法是用%运算符,但再考虑一下,似乎按位与也能判断奇偶性。用%会慢很多吗?细思恐极…以前类似情况都是用的%运算符…于是实验测量了一下:

    int main() {
      int x = 314159265;
      int y = 271828182;
      int z;
      int i;
      // 版本1,使用位运算:
      for (i = 0; i < 1000000000; ++i) {
        z = x & 1;
        z = y & 1;
      }
     // 版本2,使用%运算符:
      for (i = 0; i < 1000000000; ++i) {
        z = x % 2;
        z = y % 2;
      }
      return 0;
    }
    

    使用位运算的版本1略快于使用%运算符的版本2,但平均只有1%~2%的性能提升,似乎不必过度紧张...
    用IDA反编译了一下,两个版本得到的汇编代码并不相同,至于汇编层面上的性能分析...先学习一下汇编再说...
    (未完待续)

     
    • 陈文 下午12:26 on 2016年5月25日 链接地址 | 回复

      这个软件地址挂了http://dos.jinzihao.info/show.php?id=233

      • jinzihao 下午1:15 on 2016年5月25日 链接地址 | 回复

        谢谢提醒,已经补回

        • 陈文 下午11:22 on 2016年5月31日 链接地址 | 回复

          这也挂了http://dos.jinzihao.info/show.php?id=159

          • jinzihao 下午11:47 on 2016年5月31日 链接地址 | 回复

            抱歉,这个我在我的电脑上也找不到了,可能真的丢失了…

            • 陈文 下午10:47 on 2016年6月3日 链接地址

              明天我打算用免费空间搭一个本站的文件备份站,同意吗?

          • jinzihao 下午12:00 on 2016年6月4日 链接地址 | 回复

            这个网站确实没有时间打理了,我知道你要做这个,那就只好同意吧,不过希望可以加一个指向原网站的链接

          • jinzihao 下午12:02 on 2016年6月4日 链接地址 | 回复

            如果备份站效果还好的话,其实网页文件也都可以发给你,有人愿意把它做下去还是件好事

            • 陈文 下午1:35 on 2016年6月4日 链接地址

              还行,和本站访问速度相比要慢点,但服务器比较稳定,基本没挂过,就是要保持本站能访问,我要先把所有文件都下载下来

            • 陈文 下午8:56 on 2016年6月5日 链接地址

              看看效果吧http://mini536.3vkj.net/

    • 陈文 下午1:41 on 2016年6月4日 链接地址 | 回复

      你看看吧,还没放网页myhome.wap.ai

  • jinzihao pm9:37 on 2016年4月18日 链接地址 | 回复
    Tags: C++,   

    连续地访问内存TLB是否命中在运行时间上会有很大差别,例如:

    #include <stdio.h>
    
    int main() {
      int *a = new int[4096 * 4096];
      for (int i = 0; i < 4096; ++i) {
        for (int j = 0; j < 4096; ++j) {
          // a[(j << 12) + (i << 0)] = 0; // 0.4004s
          // a[(j << 11) + (i << 1)] = 0; // 0.3810s
          // a[(j << 10) + (i << 2)] = 0; // 0.3809s
          // a[(j << 9) + (i << 3)] = 0; // 0.3548s
          // a[(j << 8) + (i << 4)] = 0; // 0.3503s
          // a[(j << 7) + (i << 5)] = 0; // 0.2727s
          // a[(j << 6) + (i << 6)] = 0; // 0.2691s
          // a[(j << 5) + (i << 7)] = 0; // 0.1434s
          // a[(j << 4) + (i << 8)] = 0; // 0.1195s
          // a[(j << 3) + (i << 9)] = 0; // 0.0714s
          // a[(j << 2) + (i << 10)] = 0; // 0.0651s
          // a[(j << 1) + (i << 11)] = 0; // 0.0681s
           a[(j << 0) + (i << 12)] = 0; // 0.0825s
        }
      } 
      return 0;
    }
    

    上述程序中循环体内有13个版本的代码,每次编译只启用其中1行,注释掉其余的12行,测量运行时间。

    每次访问内存地址的增量从16KB逐次折半,到最后每次增量为4byte,内存访问操作由第一个版本100%的TLB miss,到第4个版本TLB miss开始降至50%(假设页大小为4KB),此后TLB miss比例逐次减半,直到最后几乎100%的TLB hit(1023/1024),此过程中运行时间不断下降。

    问题:最后一个版本的运行时间明显上升,且多次实验结果均无改变,不知该如何解释?

     

     
  • jinzihao pm12:41 on 2015年12月8日 链接地址 | 回复
    Tags: C++,   

    即使是为了防止溢出把C++程序里所有的int都改成了long long,如果输出的时忘了把printf(“%d”改掉也是白搭…我被这个坑死了…

     
  • jinzihao pm11:13 on 2015年12月2日 链接地址 | 回复
    Tags: C++   

    程序中出现奇怪的错误:
    已经确定某一段代码会造成segmentation fault, 然而在该段代码前加上一行printf(“Here is the segmentation fault.n”); ,则可以消除segmentation fault, 且运行结果正确.
    前面加上的这一行printf看起来毫无副作用, 但却造成后面的运行结果完全不同.
    发生这种情况多是由于后面的代码中有些变量没有赋初值, 其值仍为该寄存器或该段内存原有的值, 而在前面的一行printf, 看起来虽无副作用, 但一定会涉及寄存器(或者内存)的操作, 从而改写了未赋初值的变量的初值.

     
  • jinzihao pm6:02 on 2015年11月26日 链接地址 | 回复
    Tags: C++   

    C++程序中大量使用new会拖慢速度,对于有些题可能就超时了,这是因为每次new都需要动态分配一块内存。如何降低此处的时间开销?用placement new(注意第1行和第8行):

    #include 
    ......
    char *space = new char[1 << 29];
    int offset = 0;
    MyClass* instance[1000000];
    for (int i = 0; i < 1000000; ++i) {
        offset += sizeof(MyClass);
        instance[i] = new(space + offset) MyClass;
    }
    ......
    

    每次新建MyClass对象时,通过placement new手动指定它在内存中的位置,可以大大降低new的时间开销。
    实际上offset += sizeof(MyClass)一行中,每次offset自增的量常常可以略微小于sizeof(MyClass),在内存限制特别苛刻的题目中可以通过实验找出最小增量。

     
  • jinzihao pm7:02 on 2015年10月16日 链接地址 | 回复
    Tags: C++,   

    在OJ上做输入输出量很大的题时,在main()函数开头加两句:(在C中改用malloc(1 << 20)效果相同)

    	setvbuf(stdin, new char[1 << 20], _IOFBF, 1 << 20);
    	setvbuf(stdout, new char[1 << 20], _IOFBF, 1 << 20);
    

    通过创建一个足够大的输入输出缓冲区,可以减少IO操作的频率,提高IO性能。在实际测试中最多达到了300%的性能提升。
    这样看起来似乎有内存泄漏,但由于缓冲区的使命完成之时便是程序结束之时,程序结束时该段内存自然被释放,所以并不必担心内存泄漏。实际上,如果提前对该块内存进行delete[] 操作,是会造成运行时错误的。

     
  • jinzihao pm5:12 on 2015年10月10日 链接地址 | 回复
    Tags: C++,   

    对于浮点数a、b、c,if (a > b * c) 和 if (a / b > c)两种写法等价,但前者明显快于后者。

     
  • jinzihao pm5:40 on 2015年10月9日 链接地址 | 回复
    Tags: C++   

    在C++的algorithm库中有一个random_shuffle()函数,可以对任意两个迭代器(iterator)之间的序列随机打乱,例:

    srand(time(0));
    int array[100];
    for (int i = 0; i < 100; ++i) {
    	array[i] = i;
    }
    std::random_shuffle(array, array + 100);
    for (int i = 0; i < 100; ++i) {
    	printf("%d ", array[i]);
    }
    

    输出的即为0~99的一个随机排列。
    注意:和rand()函数一样,random_shuffle()在使用前需要用srand()设置随机数种子。

     
  • jinzihao pm4:44 on 2015年10月9日 链接地址 | 回复
    Tags: C++,   

    在C++中如果需要移动数组,首选string.h里面的memcpy;如果源数组和目标数组有重叠,则改用string.h里面的memmove;尽量不要手写for循环来移动数组,性能上很难超过内置函数。

     
  • jinzihao pm2:01 on 2015年10月9日 链接地址 | 回复
    Tags: C++,   

    (接前一条状态)另外,考虑功能相同的两种写法:

    s2Bit = ((((((((s2[k - 8] * 10 + s2[k - 7]) * 10 + s2[k - 6]) * 10) + s2[k - 5]) * 10 + s2[k - 4]) * 10 + s2[k - 3]) * 10 + s2[k - 2]) * 10 + s2[k - 1]) * 10 + s2[k]; 
    

    s2Bit = s2[k - 8] * 100000000 + s2[k - 7] * 10000000 + s2[k - 6] * 1000000 + s2[k - 5] * 100000 + s2[k - 4] * 10000 + s2[k - 3] * 1000 + s2[k - 2] * 100 + s2[k - 1] * 10 + s2[k];
    

    在性能上后者更有优势,但差别有限(与程序的其他部分分摊后大约节省了14%的时间)

     
c
写新的
j
下一篇文章/下一个回复
k
前一篇文章/以前的回复
r
回复
e
编辑
o
显示/隐藏 回复
t
回到顶部
l
go to login
h
show/hide help
shift + esc
取消