ゲームプログラミングの都市伝説
をテンプレートにして作成
Check
[
トップ
] [
新規
|
一覧
|
単語検索
|
最終更新
|
ヘルプ
]
開始行:
#counter
* ゲームプログラミングにおけるC++の都市伝説 [#x9f442ee]
この記事は、[[''C++ Advent Calendar 2012''>http://partake...
-Prev 21日目の記事 [[CEANによる配列操作>http://d.hatena.n...
-Next 23日目の記事 [[構造化並列プログラミング>http://d.ha...
時間の関係で3つの都市伝説しかご紹介できませんでしたが、ま...
2012/12/22 written by h.godai @hgodai
目次
-[[初めに>#k5a59394]]
-[[都市伝説1 C++は遅いのでゲームには向いていない>#o889d...
-[[都市伝説2 boost::poolはゲームには向いていない>#s3ca2...
-[[都市伝説3 boostライブラリは怪しいライブラリだ。使う...
*初めに [#k5a59394]
かつて、8bit時代はゲームのプログラムはアセンブラが主流で...
1990年代後半から、C++の開発環境が整備され、ゲームプログラ...
C++はゲームプログラミングに向いていないのでしょうか? も...
ここでは、C++にまつわる都市伝説を通して誤解を解いていきた...
* 都市伝説1 C++は遅いのでゲームには向いていない [#o889d...
1990年ごろ、私が初めてC++に触れたとき、C++は遅いと感じま...
私自身、テンプレートが使えるようになるまで、C++は遅いと思...
では、C言語とC++で書かれた等価なプログラムの実行速度を測...
速度の計測は、CPUのカウンタを使用したAPIを使っています。W...
コンパイルオプションは、それぞれ速度に対して最高レベルの...
テストプログラムは、10万回~100万回ほどのループを10回繰り...
残念ながらC++11でのテスト環境がそろっていないため、C++03...
**検証1 世界で最も多くの人が実行するプログラム、「Hello...
-プログラムリスト
--C言語
printf(“Hello world\n”);
--C++言語
cout << “Hello world!” << endl;
-結果
#ref(CppAdvent_1-1.png)
C++標準ライブラリのstreamクラスは高機能で複雑な処理を行う...
** 検証2 文字列の全文検索 (strstr vs std::string) [#nf51e...
つぎは、もう少し複雑なプログラムということで、char*型の文...
被検索対象は約45KBのテキスト文字で、boost/foreach.hpp の...
-プログラム
-- C言語
const char* p = source_text; // boost/foreach.hpp...
const char* search_text = "BOOST";
size_t tlen = strlen(search_text);
uint32_t found = 0;
while (p && *p) {
p = strstr(p, search_text);
if (p) {
++found;
p += tlen; // size of 'BOOST'
}
}
-- C++言語
string text(source_text); // boost/foreach.hppの内容
string search_text("BOOST");
uint32_t found = 0;
string::size_type p = 0;
while (p != string::npos) {
p = text.find(search_text, p);
if (p != string::npos) {
++found;
p += search_text.length(); // size of 'BOOST'
}
}
- 結果
#ref(CppAdvent_1-2.png)
ポインタを直接操作するC言語のシンプルなstrstr関数にくらべ...
この2つのプログラムをよく見てください。普通に考えれば、ど...
機能的にはC++のコンテナやアルゴリズムが圧倒しているので、...
** 検証3 ビットマップのピクセル処理 (C vs #define vs C++ ...
検証2でC++が良いスコアを出したのは、最適化によるインライ...
検証3では、C言語の関数コールによる処理と、#defineマクロ...
対象となるテストプログラムは、RGBが5:6:5bitの16bit/pixel...
-プログラム
--C言語(関数コール)
int get_r(short x) { return ((x >> 8) & 0xf8); }
int get_g(short x) { return ((x >> 3) & 0xfc); }
int get_b(short x) { return ((x << 3) & 0xff); }
short to_rgb(int r, int g, int b) {
return (short)(((r << 8) & 0xf800) | ((g << 3) & 0x07e...
}
void test_bitmap_color_transform_pure_c(short* buffer) {
short* p = buffer;
int n;
for (n = 0; n < IMAGE_HEIGHT * IMAGE_WIDTH; ++n, ++p) {
int r = get_r(*p);
int g = get_g(*p);
int b = get_b(*p);
*p = to_rgb(g, b, r);
}
}
--C言語(マクロ)
#define GET_R(x) ((x >> 8) & 0xf8)
#define GET_G(x) ((x >> 3) & 0xfc)
#define GET_B(x) ((x << 3) & 0xff)
#define TO_RGB(r, g, b) (((r << 8) & 0xf800) | ((g << 3)...
void test_bitmap_color_transform_macro_c(short* buffer) {
short* p = buffer;
int n;
for (n = 0; n < IMAGE_HEIGHT * IMAGE_WIDTH; ++n, ++p) {
int r = GET_R(*p);
int g = GET_G(*p);
int b = GET_B(*p);
*p = (short)TO_RGB(g, b, r);
}
}
--C++言語(テンプレート)
template <int PixelBits>
struct pixel_t {};
template <>
struct pixel_t<16> {
uint16_t value_;
pixel_t() : value_(0) {}
pixel_t(int r, int g, int b)
: value_(static_cast<uint16_t>(((r << 8) & 0xf800...
{}
int get_r() const { return (value_ >> 8) & 0xf8; }
int get_g() const { return (value_ >> 3) & 0xfc; }
int get_b() const { return (value_ << 3) & 0xff; }
};
struct transcolor {
template <typename Pixel>
void operator () (Pixel& px) {
px = Pixel(px.get_g(), px.get_b(), px.get_r());
}
};
void test_bitmap_color_transform_cpp(vector< pixel_t<16...
for_each(buffer, transcolor());
}
- 結果
#ref(CppAdvent_1-3.png)
この結果から、#defineマクロによる展開がまったく無意味なこ...
そして、このような比較的単純な処理でもC++のほうが高速な結...
古いコードをC++用に書きなおすだけで処理速度が半分以下にな...
** 検証4 ソートライブラリ (libc vs STL) [#hefa1303]
最後の検証は、わりとよくあるやつ。qsort vs sortです。結果...
double x,y,zという要素をもつ100万個のオブジェクトのソート...
100万個のオブジェクトは、あらかじめ乱数で埋めておきます。...
-プログラム
--C言語
typedef struct Element {
double x,y,z;
} Element;
int compare(const void* va, const void* vb) {
const Element* a = (const Element*)va;
const Element* b = (const Element*)vb;
if (a->x+a->y+a->z < b->x+b->y+b->z) return 1;
if (a->x+a->y+a->z > b->x+b->y+b->z) return -1;
return 0;
}
...
const size_t ELEMENT_SIZE = 1000000;
Element* element = (Element*)malloc(ELEMENT_SIZE * size...
// setup random value to element
qsort(element, ELEMENT_SIZE, sizeof(Element), compare);
--C++言語
struct Element {
double x,y,z;
bool operator () (const Element& a, const Element& b)...
return a.x+a.y+a.z < b.x+b.y+b.z;
}
};
...
const size_t ELEMENT_SIZE = 1000000;
vector<Element> element(ELEMENT_SIZE);
// setup random value to element
sort(element.begin(), element.end(), Element());
- 結果
#ref(CppAdvent_1-4.png)
予想通り''C++の圧勝''です。VisualStudioでは''2.5倍''、gcc...
もう、議論の余地はありません。もし、qsort()を使っている個...
** 結論 [#mcdd6e06]
ほとんどの処理で、''C++はCよりも高速に動作します''。しか...
レガシーなCで書かれたプログラムを、C++で書きなおすにはそ...
C++はゲームプログラミングにおいて、少なくともC言語よりは...
* 都市伝説2 boost::poolはゲームには向いていない [#s3ca2...
ゲームプログラミングにおいて、メモリーの管理は重要です。...
これらの問題を一気に解決してくれそうなライブラリがboostに...
そんな便利なboost poolライブラリですが、''「ゲームには向...
さっそく、「都市伝説1」で使用した速度計測ツールを使って...
-プログラム
uint64_t* ptrs_[100000];
boost::object_pool<uint64_t> intpool;
for (int n = 0; n < 100000; ++n) {
// 計測開始
ptrs_[n] = intpool.malloc();
// 計測終了
}
-結果
#ref(CppAdvent_2-1.png)
ごらんのとおり。10万回のmallocのほとんどが300ナノ秒以下で...
STLやboostに精通されている皆さんならこのグラフを見ただけ...
boost poolはvectorと同じように、メモリーの動的な確保を''...
解決方法は簡単です。object_poolのコンストラクタに、あらか...
-プログラム
uint64_t* ptrs_[100000];
boost::object_pool<uint64_t> intpool(100000);
for (int n = 0; n < 100000; ++n) {
// 計測開始
ptrs_[n] = intpool.malloc();
// 計測終了
}
-結果
#ref(CppAdvent_2-2.png)
見事に平坦なグラフになりました。初回だけ、メモリー確保の...
boost poolのコンストラクタにサイズを指定ができるとうこと...
同様に、std::vectorにpush_backを行うようなプログラムの場...
正しく使えば、boost poolはゲームプログラミングにおいて非...
* 都市伝説3 boostライブラリは怪しいライブラリだ。使うと...
残念なことに、C++のプログラマ以外の人々には''boostライブ...
-証言1 boost愛好者は、秘密の組織を作って''定期的に集会を...
-証言2 boostは''「[[魔道書>http://longgate.co.jp/products...
-証言3 一度でもboostを使った者は、''二度とboostなしでは生...
-証言4 boostの深い所まで踏み込んでしまった者は、''魔術的...
はい。これらは確かに事実かもしれませんが、boostは決して怪...
ただし、仕事でboostライブラリを使用する際は、''用法用量を...
終了行:
#counter
* ゲームプログラミングにおけるC++の都市伝説 [#x9f442ee]
この記事は、[[''C++ Advent Calendar 2012''>http://partake...
-Prev 21日目の記事 [[CEANによる配列操作>http://d.hatena.n...
-Next 23日目の記事 [[構造化並列プログラミング>http://d.ha...
時間の関係で3つの都市伝説しかご紹介できませんでしたが、ま...
2012/12/22 written by h.godai @hgodai
目次
-[[初めに>#k5a59394]]
-[[都市伝説1 C++は遅いのでゲームには向いていない>#o889d...
-[[都市伝説2 boost::poolはゲームには向いていない>#s3ca2...
-[[都市伝説3 boostライブラリは怪しいライブラリだ。使う...
*初めに [#k5a59394]
かつて、8bit時代はゲームのプログラムはアセンブラが主流で...
1990年代後半から、C++の開発環境が整備され、ゲームプログラ...
C++はゲームプログラミングに向いていないのでしょうか? も...
ここでは、C++にまつわる都市伝説を通して誤解を解いていきた...
* 都市伝説1 C++は遅いのでゲームには向いていない [#o889d...
1990年ごろ、私が初めてC++に触れたとき、C++は遅いと感じま...
私自身、テンプレートが使えるようになるまで、C++は遅いと思...
では、C言語とC++で書かれた等価なプログラムの実行速度を測...
速度の計測は、CPUのカウンタを使用したAPIを使っています。W...
コンパイルオプションは、それぞれ速度に対して最高レベルの...
テストプログラムは、10万回~100万回ほどのループを10回繰り...
残念ながらC++11でのテスト環境がそろっていないため、C++03...
**検証1 世界で最も多くの人が実行するプログラム、「Hello...
-プログラムリスト
--C言語
printf(“Hello world\n”);
--C++言語
cout << “Hello world!” << endl;
-結果
#ref(CppAdvent_1-1.png)
C++標準ライブラリのstreamクラスは高機能で複雑な処理を行う...
** 検証2 文字列の全文検索 (strstr vs std::string) [#nf51e...
つぎは、もう少し複雑なプログラムということで、char*型の文...
被検索対象は約45KBのテキスト文字で、boost/foreach.hpp の...
-プログラム
-- C言語
const char* p = source_text; // boost/foreach.hpp...
const char* search_text = "BOOST";
size_t tlen = strlen(search_text);
uint32_t found = 0;
while (p && *p) {
p = strstr(p, search_text);
if (p) {
++found;
p += tlen; // size of 'BOOST'
}
}
-- C++言語
string text(source_text); // boost/foreach.hppの内容
string search_text("BOOST");
uint32_t found = 0;
string::size_type p = 0;
while (p != string::npos) {
p = text.find(search_text, p);
if (p != string::npos) {
++found;
p += search_text.length(); // size of 'BOOST'
}
}
- 結果
#ref(CppAdvent_1-2.png)
ポインタを直接操作するC言語のシンプルなstrstr関数にくらべ...
この2つのプログラムをよく見てください。普通に考えれば、ど...
機能的にはC++のコンテナやアルゴリズムが圧倒しているので、...
** 検証3 ビットマップのピクセル処理 (C vs #define vs C++ ...
検証2でC++が良いスコアを出したのは、最適化によるインライ...
検証3では、C言語の関数コールによる処理と、#defineマクロ...
対象となるテストプログラムは、RGBが5:6:5bitの16bit/pixel...
-プログラム
--C言語(関数コール)
int get_r(short x) { return ((x >> 8) & 0xf8); }
int get_g(short x) { return ((x >> 3) & 0xfc); }
int get_b(short x) { return ((x << 3) & 0xff); }
short to_rgb(int r, int g, int b) {
return (short)(((r << 8) & 0xf800) | ((g << 3) & 0x07e...
}
void test_bitmap_color_transform_pure_c(short* buffer) {
short* p = buffer;
int n;
for (n = 0; n < IMAGE_HEIGHT * IMAGE_WIDTH; ++n, ++p) {
int r = get_r(*p);
int g = get_g(*p);
int b = get_b(*p);
*p = to_rgb(g, b, r);
}
}
--C言語(マクロ)
#define GET_R(x) ((x >> 8) & 0xf8)
#define GET_G(x) ((x >> 3) & 0xfc)
#define GET_B(x) ((x << 3) & 0xff)
#define TO_RGB(r, g, b) (((r << 8) & 0xf800) | ((g << 3)...
void test_bitmap_color_transform_macro_c(short* buffer) {
short* p = buffer;
int n;
for (n = 0; n < IMAGE_HEIGHT * IMAGE_WIDTH; ++n, ++p) {
int r = GET_R(*p);
int g = GET_G(*p);
int b = GET_B(*p);
*p = (short)TO_RGB(g, b, r);
}
}
--C++言語(テンプレート)
template <int PixelBits>
struct pixel_t {};
template <>
struct pixel_t<16> {
uint16_t value_;
pixel_t() : value_(0) {}
pixel_t(int r, int g, int b)
: value_(static_cast<uint16_t>(((r << 8) & 0xf800...
{}
int get_r() const { return (value_ >> 8) & 0xf8; }
int get_g() const { return (value_ >> 3) & 0xfc; }
int get_b() const { return (value_ << 3) & 0xff; }
};
struct transcolor {
template <typename Pixel>
void operator () (Pixel& px) {
px = Pixel(px.get_g(), px.get_b(), px.get_r());
}
};
void test_bitmap_color_transform_cpp(vector< pixel_t<16...
for_each(buffer, transcolor());
}
- 結果
#ref(CppAdvent_1-3.png)
この結果から、#defineマクロによる展開がまったく無意味なこ...
そして、このような比較的単純な処理でもC++のほうが高速な結...
古いコードをC++用に書きなおすだけで処理速度が半分以下にな...
** 検証4 ソートライブラリ (libc vs STL) [#hefa1303]
最後の検証は、わりとよくあるやつ。qsort vs sortです。結果...
double x,y,zという要素をもつ100万個のオブジェクトのソート...
100万個のオブジェクトは、あらかじめ乱数で埋めておきます。...
-プログラム
--C言語
typedef struct Element {
double x,y,z;
} Element;
int compare(const void* va, const void* vb) {
const Element* a = (const Element*)va;
const Element* b = (const Element*)vb;
if (a->x+a->y+a->z < b->x+b->y+b->z) return 1;
if (a->x+a->y+a->z > b->x+b->y+b->z) return -1;
return 0;
}
...
const size_t ELEMENT_SIZE = 1000000;
Element* element = (Element*)malloc(ELEMENT_SIZE * size...
// setup random value to element
qsort(element, ELEMENT_SIZE, sizeof(Element), compare);
--C++言語
struct Element {
double x,y,z;
bool operator () (const Element& a, const Element& b)...
return a.x+a.y+a.z < b.x+b.y+b.z;
}
};
...
const size_t ELEMENT_SIZE = 1000000;
vector<Element> element(ELEMENT_SIZE);
// setup random value to element
sort(element.begin(), element.end(), Element());
- 結果
#ref(CppAdvent_1-4.png)
予想通り''C++の圧勝''です。VisualStudioでは''2.5倍''、gcc...
もう、議論の余地はありません。もし、qsort()を使っている個...
** 結論 [#mcdd6e06]
ほとんどの処理で、''C++はCよりも高速に動作します''。しか...
レガシーなCで書かれたプログラムを、C++で書きなおすにはそ...
C++はゲームプログラミングにおいて、少なくともC言語よりは...
* 都市伝説2 boost::poolはゲームには向いていない [#s3ca2...
ゲームプログラミングにおいて、メモリーの管理は重要です。...
これらの問題を一気に解決してくれそうなライブラリがboostに...
そんな便利なboost poolライブラリですが、''「ゲームには向...
さっそく、「都市伝説1」で使用した速度計測ツールを使って...
-プログラム
uint64_t* ptrs_[100000];
boost::object_pool<uint64_t> intpool;
for (int n = 0; n < 100000; ++n) {
// 計測開始
ptrs_[n] = intpool.malloc();
// 計測終了
}
-結果
#ref(CppAdvent_2-1.png)
ごらんのとおり。10万回のmallocのほとんどが300ナノ秒以下で...
STLやboostに精通されている皆さんならこのグラフを見ただけ...
boost poolはvectorと同じように、メモリーの動的な確保を''...
解決方法は簡単です。object_poolのコンストラクタに、あらか...
-プログラム
uint64_t* ptrs_[100000];
boost::object_pool<uint64_t> intpool(100000);
for (int n = 0; n < 100000; ++n) {
// 計測開始
ptrs_[n] = intpool.malloc();
// 計測終了
}
-結果
#ref(CppAdvent_2-2.png)
見事に平坦なグラフになりました。初回だけ、メモリー確保の...
boost poolのコンストラクタにサイズを指定ができるとうこと...
同様に、std::vectorにpush_backを行うようなプログラムの場...
正しく使えば、boost poolはゲームプログラミングにおいて非...
* 都市伝説3 boostライブラリは怪しいライブラリだ。使うと...
残念なことに、C++のプログラマ以外の人々には''boostライブ...
-証言1 boost愛好者は、秘密の組織を作って''定期的に集会を...
-証言2 boostは''「[[魔道書>http://longgate.co.jp/products...
-証言3 一度でもboostを使った者は、''二度とboostなしでは生...
-証言4 boostの深い所まで踏み込んでしまった者は、''魔術的...
はい。これらは確かに事実かもしれませんが、boostは決して怪...
ただし、仕事でboostライブラリを使用する際は、''用法用量を...
ページ名: