No Such Blog or Diary

«Prev || 1 | 2 | 3 |...| 9 | 10 | 11 |...| 57 | 58 | 59 || Next»

gcc 4.5.0 (experimental) でラムダ式をデマングルしてみた

#include <iostream>
#include <typeinfo>
#include <cxxabi.h>
 
int main(int argc, char *argv[])
{
  auto f = [](int a) { return (a + 1) ^ 7;};
  int status;
  std::cout << abi::__cxa_demangle((typeid (f)).name(), 0, 0, &status) << std::endl;
  auto g = [](int a, float b) { return ((a + 1) ^ 7) + b;};
  std::cout << abi::__cxa_demangle((typeid (g)).name(), 0, 0, &status) << std::endl;
  auto h = [](int a, float b) { return ((a + 1) ^ 7) + b;};
  std::cout << abi::__cxa_demangle((typeid (h)).name(), 0, 0, &status) << std::endl;
  std::cout << abi::__cxa_demangle((typeid (h(1,1.0f))).name(), 0, 0, &status) << std::endl;
  return 0;
}

を実行して

main::{lambda(int)#1}
main::{lambda(int, float)#2}
main::{lambda(int, float)#3}
float

が出力された.

とりあえず,宣言された場所+lambdaに引数が連なって,ついでに何番目に宣言されたかがくっつくと.なるほど.

gcc 4.5.0 (experimental) でラムダ式使ってみた

gccのsvnにある4.5.0ならc++0xのλ式が使えるのでgccをコンパイルしてインストールしてみた.

とりあえず std::transform を一行でかけるのかなぁと以下のコードを書いてコンパイル.オプションに -std=gnu++0xを指定.

#include <iostream>
#include <algorithm>
#include <vector>
 
int main(int argc, char *argv[])
{
  std::vector<int> x;
  int n = 10;
  for(int i = 0; i < n; i++) x.push_back(i);
  for(auto it = x.begin(); it != x.end(); it++) std::cout << " " << (*it);
  std::cout << std::endl;
  std::transform(x.begin(), x.end(), x.begin(), [](int a) { return (a + 1) ^ 7;});
  for(auto it = x.begin(); it != x.end(); it++) std::cout << " " << (*it);
  std::cout << std::endl;
  return 0;
}

そしたら普通にコンパイルが通って,実行したら配列要素がちゃんとインクリメントされていた.

ちなみに,上のプログラムのtransformのメインループは

L42:
        movl    (%rax), %edx
        addq    $1, %rcx
        addl    $1, %edx
        xorl    $7, %edx
        movl    %edx, (%rax)
        addq    $4, %rax
        cmpq    %rcx, %rbx
        ja      L42

のようにコンパイルされた(-O3 オプションで).λ式だと変なオーバーヘッドが入らないらしい.boostのlambdaないしfunctionsあたりだと変なオーベーヘッドが掛かってたけど,c++0xのλ式だとその心配がなく簡単に使える.ただし,このλ式を変数に代入したりしたときにどうなるかはまだ試してない.

CMOVLとかあったのね

コンパイルされたアセンブリ見てたら CMOVL とかいう命令が使われてた.conditional move if less の意味らしい.つーかこんな命令今まで気にしてなかったけど存在してたのね.

http://www.asmpedia.org/とかx86の命令が色々書いてあって便利そう.

さてどうしてか

同じように書いたコードが倍の速度差になる.テンプレート関数を手で展開したのと,元のままにしたものとで,なぜか手で展開したほうのが倍遅い….答えが同じなので同じ計算をしているはずなのだが,何か最適化の聞き具合が違うのだろうか? なぞだ.

ようやく64bitでも頭よく最適化してくれるようになった

const だからコピーしまくっても最適化時にひとつになるだろう、とか思って手を抜いた実装になっていた部分をコピーが無くなる様に改善した.そしたら無駄なことしない最適化されたコードを吐いてくれるようになった.

……あれ? 手で最適化しただけの様に思えてきた…… ま,いっか.

const 万歳

色々付けまくったらコンパイラががんばって最適化してくれるようになった! でもなぜか32bitバイナリへのコンパイル時にしか頭良くない.同じコンパイラなのに(?)64bitへのコンパイルだと頭悪い子になってしまう… もう少し明示的に無駄を省くしかないか.

«Prev || 1 | 2 | 3 |...| 9 | 10 | 11 |...| 57 | 58 | 59 || Next»
Search
Feeds

Page Top