C/C++

ysd@KLab > C/C++

C言語系

マルチスレッド(pthread)

  1. ヘッダファイル
    #include <pthread.h>
    をインクルードする必要があります。(コンパイルオプションに -lpthread も。)
  2. スレッドを管理する変数
    pthread_t hoge;
    という pthread_t 型の変数を用意します。1スレッドあたり1つ必要なので、複数スレッドを立ち上げる場合は配列にでもしてください。
  3. スレッドとして呼び出す関数の作成
    void* function(void* arg);
    引数・帰り値ともにvoid*型という決まりになっていますので、他の型を使いたいときは内部・外部でキャストします。
  4. スレッド呼び出し
    pthread_create(&hoge, NULL, function, (void*)fuga);
    で呼び出せます。fuga は関数に渡す引数のポインタです。1つしか渡せないので、複数の値の入出力をしたいときは新たな構造体を作ってください。

排他処理(mutex)

マルチスレッド処理をしているときに、複数のスレッドが(ほぼ)同時に同じ変数に書き込もうとするのを防ぐためのものです。
  1. ヘッダファイル
    マルチスレッドで使うものなので
    #include <pthread.h>
    をインクルードする必要があります。
  2. 管理する変数&初期化
    pthread_mutex_t hoge = PTHREAD_MUTEX_INITIALIZER;
    1つの変数に複数のスレッドが同時にロックをかけることはできません。あるスレッドがロックしている間、他のスレッドはロックすることができず、待ちぼうけということになります。規定数まで受け付けてそれ以上を待たせるという処理にはセマフォという別物があります。
  3. ロック・アンロック
    pthread_mutex_lock(&hoge);   // ロック
    pthread_mutex_unlock(&hoge); // アンロック
    ロックをしようとするときに、既にその変数がロックされている場合は、アンロックされるまで待ち続けることになります。

時間計測

#include <sys/time.h>
double myclock(void)
{
  struct timeval t;
  gettimeofday(&t, NULL);
  return t.tv_sec + t.tv_usec * 1e-6;
}
上記のようにヘッダのインクルードと関数を書いておくと
double st, ed;
st = myclock();
// 時間計測したい部分を入れる
ed = myclock();
printf("かかった時間は %.6f 秒です\n", ed - st);
とすることで、マイクロ秒(10-6秒)単位で計測できます。

区間限定・倍速剰余演算

そもそもの問題としては、Nが固定値でnが様々に変わるとき、n mod Nの演算をどのように行うか、ということである。まずはごくごく一般的な解答を。

amari = n % N;

次は%演算が遅いと言って、普段から浮動小数を使いまくっている人ならこうするかもという例。

NINV = 1.0 / N;
amari = n - (int)((double)n * NINV) * N;

勿論 NINV は最初に1回計算するだけで、nが変わるたびに計算する必要が無いようにする訳である。結構高速。そして今回の肝は次のやつ。

amari = n - ((n * A) >> B) * N;

実はこれ、nの範囲に制限がある(それ以外では違った値を出す可能性がある)。でもとても高速。

後で定数項の算出方法は書くけど、今は取りあえず例だけ。

NAB有効範囲
93641150≤n<32768
1026215180≤n<43699
112979150≤n<32769

ついでに、除算自体で同様のことをしてみる。演算は
sho = (n * A) >> B; (== n / N)
NAB有効範囲
97282160≤n<32768
106554160≤n<16389
115958160≤n<32768

C++系

ostreamの書式設定

何はともあれincludeするもの、と面倒くさいのでデフォルト名前空間宣言。

#include <iostream>
#include <iomanip>
using namespace std;

あとは要点だけ。コメント以降が対応する printf 書式設定。

int n;
double x;
cout << setiosflags(ios::fixed); // 固定小数表記に設定する
cout << setw(10) << n;           // printf("%10d", n);   実効桁数
cout << setw(10) << str;         // printf("%10s", str); 文字列でも使える
cout << hex << n;                // printf("%x", n);     16進表記
cout << setprecision(5) << x;    // printf("%.5f", x);   有効桁数なので若干 printf と違う

algorithm::sort()で比較関数オブジェクトを使う

正直、毎回使い方を忘れるのでメモ。

#include <vector>
#include <algorithm>
using namespace std;

struct date { int year, month, day; }; // 日付クラスを自己定義。参照しやすいので構造体
class compDate {                       // 比較関数。名前はテキトーに。構造体でもできるんじゃないかな?
public:
  bool operator()(const date& left, const date& right) const {
    if( left.year < right.year ) return true;
    if( left.year > right.year ) return false;
    if( left.month < right.month ) return true;
    if( left.month > right.month ) return false;
    return left.day < right.day;
  }
};

void function()
{
  vector<date> v(100); // 適当にデータが入っているとする
  sort(v.begin(), v.end(), comp());
}