doridoridoriand’s diary

主に技術的なことを書いていく予定(たぶん)

雑記

だれかNginxのリバースプロキシの設定教えてくれー。うごかんー

さて本当は色々書きたいことあるんだけど、記事にするにはまだ調査不足だし中途半端だしのネタを箇条書きにしてある(だけ)のエントリーだよ(ぉ

  • GIL(Global Intterspreter Lock)について色々な言語の対応状況まとめる
  • Cocos2dやりだしたし、せっかくならC++をもっとやりこもう。最近のC++すごいモダンだし(小並感)
  • HUGOのテーマ作る
  • サーバーサイドJavaScriptと真剣に向き合う
  • 無線LANルーター壊れかけたので、新しいの欲しい
  • PHPバージョン7ってなんぞや5.6(最新の安定版)より2倍早いらしいけど本当??
  • CUDA ああCUDA
  • 広角の一眼のレンズ欲しい。何がいいかしら

・・・

それにしても暑いですね。僕は完全に夏バテしてしまいました。あと寝不足。あつい 個人的に静的サイトブームなので、ある程度までならCMSいらない感じのHUGOテーマつくろうって思っている(行動しているわけではない)

と言いつつ最近サーバーサイドで書いているのはSinatraですが。。。

GPUのまとめ3

いい加減コードを示していくよw

とりあえずコードを書きます 先にCUDAのドライバーなどがインストールされていること前提で進めています。そのうちインストール方法とかまとめます(ほんとか??)

#include <iostream>
#include <malloc.h>
#include <helper_cuda.h>

# define N           (8192 * 8192)
# define block_size  196608
# define thread_size 512

__global__ void add( int *a, int *b, int *c) {
  int thread_id = blockIdx.x * blockDim.x + threadIdx.x;
  while (thread_id < N) {
    c[thread_id] = a[thread_id] + b[thread_id];
    thread_id += gridDim.x;
  }
}

int main(int argc, char** argv) {
  int *a, *b, *c;
  ind *dev_a, *dev_b, *dev_c;

  a = (int*)malloc(N * sizeof(int));
  b = (int*)malloc(N * sizeof(int));
  c = (int*)malloc(N * sizeof(int));

  cudaMalloc((void**)&dev_a, N * sizeof(int));
  cudaMalloc((void**)&dev_b, N * sizeof(int));
  cudaMalloc((void**)&dev_c, N * sizeof(int));

  for (int i = 0; i < N; i++) {
    a[i] = i;
    b[i] = 2 * i;
  }

  cudaMemcpy(dev_a, a, N * siezeof(int), cudaMemcpyHostToDevice);
  cudaMemcpy(dev_b, b, N * siezeof(int), cudaMemcpyHostToDevice);

  add<<<block_size, thread_size>>>(dev_a, deb_b, dev_c);

  cudamemcpy(c, dev_c, N * sizeof(int), cudaMemcpyDeviceToHost);

  cudaFree(dev_a);
  cudaFree(dev_b);
  cudaFree(dev_c);

  free(a);
  free(b);
  free(c);

  return 0;
}

上から説明していきます。CUDA独自の書き方とかまあ色々説明しなければならないことはあるのですが、まあ適宜最小限の説明で行きます。 最初に色々言われても実際のコード見ないとわからないこと多いもんね

# define N           (8192 * 8192)
# define block_size  196608
# define thread_size 512

まずここの定数宣言なんだって感じですよね

# define N (8192 * 8192)

今回はCUDAの性能を純粋に測りたかったので単純なベクトル和を計算するのを書いています。 よってこれは計算するベクトルの総和。つまり計算対象は 8192 * 8192 あるってことです

# define block_size  196608

使用するブロック数です。これテキトー(というか、さっきまで使ってたGPUに合わせただけ)なので、適宜変えて大丈夫です。これを変えて処理時間とか見みると結構面白い

define thread_size 512

使用するスレッド数です。これも変えておk

__global__ void add( int *a, int *b, int *c) {
  int thread_id = blockIdx.x * blockDim.x + threadIdx.x;
  while (thread_id < N) {
    c[thread_id] = a[thread_id] + b[thread_id];
    thread_id += gridDim.x;
  }
}

これが今回のメインの話題となるやつですね

__global__ってついたやつはコンパイル時にGPU用のコードとしてコンパイルされます。 もっと正確にいうと、コンパイルnvccというnVIDIAコンパイラを使うのですが、コンパイルの流れとしては

  • コンパイル実行 nvcc -o hoge hoge.cu
  • nvccがCPUコードとGPUコードを判別。CPU用はgccに渡し、GPU用はnvccが担当する
  • 最後CPU側がGPUバイトコードを呼ぶような感じでリンクして実行ファイル生成(めっちゃ適当)

ってなっていますGPU側はPTXコードというのが生成されたり色々するのですが、 僕があんま詳しくないのでもう少し詳しく取り扱いたいのでまた今度

int thread_id = blockIdx.x * blockDim.x + threadIdx.x;

これがGPUの特徴をよく表していると個人的に思うのですが、並列計算をするときに、SP同士でメモリの参照が狂ったりしないようにそれぞれの順番をuniqになるように定義できるのです。 ちなみに使用するスレッドが1つだけの場合、つまり# define thread_size 1のときはthreadIdxはいらなくて良かったりします

以下はとくに変ではない、ふつうのCに登場してくるwhile文なので説明は省略します。
ではメイン関数をば

int *a, *b, *c;
ind *dev_a, *dev_b, *dev_c;

初期化はポインタで指定してね。でないと参照渡しとか出来ないので

cudaMalloc((void**)&dev_a, N * sizeof(int));
cudaMalloc((void**)&dev_b, N * sizeof(int));
cudaMalloc((void**)&dev_c, N * sizeof(int));

これでcuda側のメモリ確保を行います。

for (int i = 0; i < N; i++) {
  a[i] = i;
  b[i] = 2 * i;
}

ベクトル和の値の初期化をしてるだけです

cudaMemcpy(dev_a, a, N * siezeof(int), cudaMemcpyHostToDevice);

これでCPU側で初期化した配列群をGPU側のグローバルメモリにコピーします

add<<<block_size, thread_size>>>(dev_a, deb_b, dev_c);

ここで先ほどのGPUのコードを呼び出しています。 <<<>>>で囲まれた部分でこの関数で使用するブロックとスレッドの数を指定できます

cudamemcpy(c, dev_c, N * sizeof(int), cudaMemcpyDeviceToHost);

ここで計算し終わったデータをGPU側からCPU側にコピーしています

cudaFree(dev_a);

みんなだいすきメモリ解放。Cのfree()のCUDA版です

すげーどんどん説明がテキトーになっているのがわかるかと思われますが、夏バテなので許してください

最後に__global__の関数、つまりCUDAで処理される関数はvoid型しか取れないのでみなさん注意してください

次回はAWSで実行環境を作る話をしたいです。僕はもうお家帰って寝たいです

最速でAPIをつくろう

写真のフランク・シナトラとは関係ないよ(たぶん)

Androidアプリを書いていて、最初はAPIいらないかと持っていたのですが、今後の実装を考えていくうちにどう考えても辛さしかないわって感じになったので速攻で作りました。
個人的にはAWSAPI Gatewayとか試したかったんですけど、今回はあまり時間がなかったので。。
(というか日程的にバックエンド開発に時間を割けないorz)

よって一番慣れているもので作りましたとさ

実際にはクローラーが稼働していて、そいつらが読み取ったデーターがMySQLにたまっている感じを想像していただけるとわかると思います。まあ今流行りのクローラーです

とりあえずgemを入れましょう

gem install sinatra

次にサクッとコードを書きます

例えばDBのテーブルがこんなかんじだったとしまして

create table `hogehoge_items` (
  `id`            int(10)      unsigned not null,
  `hoge_id`       int(10)      unsigned not null,
  `title`         varchar(255) not null,
  `link`          varchar(768) not null,
  `published`     varchar(255) not null,
  `updated`       varchar(255) not null,
  `content`       varchar(255) not null,
  primary key(`id`)
) engine=InnoDB default charset=utf8;

シンタックスハイライトすんじゃん!!びっくり!!

取り乱しました。すみません。出来ないものだとばかり思い込んでいたので。。。

DBスキーマそのまま貼っつけましたが皆さんわかると思うのでこのまま行きます

次に肝心のコードです

require 'active_record'
require 'sinatra'

db_config = YAML.load_file(File.expand_path(File.join(__FILE__, 'config', 'database.yml')))
ActiveRecord::Base.establish_connection(db_config['db']['production'])

set :root, File.expand_path(File.join(__FILE__, '..', 'static'))

get '/' do
  erb :index
end

get '/news/:hoge_id' do
  content_type :json, :charset => 'utf-8'
  entries = GoogleAlertItems.where(hoge_id: params[:hoge_id]).order('updated DESC').limit(10)
  entries.to_json(:root => false)
end

本当をいうと今回実装したのと全然構造違うのですが、説明用に変えて書いています。 とりあえず上から説明していきます

require 'active_record'
require 'sinatra'

大丈夫ですね。普通にimport#includeといった他の言語にもよくあるライブラリの読み込みです

db_config = YAML.load_file(File.expand_path(File.join(__FILE__, 'config', 'database.yml')))
ActiveRecord::Base.establish_connection(db_config['db']['production'])

ActiveRecordを単体で叩けるように設定を読み込んでいます。db_config['db']['production']部分をproductionからdevelopment変えたりすることで開発環境と本番環境を分けたりなど、色々と便利なのですが、とりあえず今回はそこまで凝ったことしなくていいので
あ。ここでdatabase.ymlは既に存在していること前提で話しています(笑)

set :root, File.expand_path(File.join(__FILE__, '..', 'static'))

Sinatraは静的ファイルのディレクトリの場所を変更することが可能です。今回は色々な関係でstaticというフォルダを指定しています

get '/' do
  erb :index
end

get '/news/:hoge_id' do
  content_type :json, :charset => 'utf-8'
  entries = GoogleAlertItems.where(hoge_id: params[:hoge_id]).order('updated DESC').limit(10)
  entries.to_json(:root => false)
end

メインディッシュですね。Sinatraの特徴はMVCアーキテクチャーに則っていないことです。乱暴に言うとCしか持っていません。そしてこれはルーティングを書いているだけです。 ちゃんと設計してあげれば立派なMVCフレームワークになるのですが、ならRails使えよって話で(笑) ちなみにSinatraをベースにMVCアーキテクチャーを持たせた設計にしてあるのがPadrinoってやつです
僕はいまいちRailsに比べての優位な部分を見いだせていないので使ったことないです。すません

get '/' do
  erb :index
end

これはサイトのトップディレクトリに来たらstaticsフォルダーにあるindex.erbrenderする処理を書いています。ちなみにhamlだろうがslimだろうが適切なgemを入れてあげれば対応できます

get '/news/:hoge_id' do
  content_type :json, :charset => 'utf-8'
  entries = GoogleAlertItems.where(hoge_id: params[:hoge_id]).order('updated DESC').limit(10)
  entries.to_json(:root => false)
end

これはなんかややこしそうですね。しかし分解して読み解けば簡単です

get '/news/:hoge_id' doでURLに含まれている/news/以下の文字列を読み取ります。よって

/news/yoshioというURLに対してアクセスが来た場合、 yoshioという文字列がsinatra側に渡されることになります

GoogleAlertItems.where(hoge_id: params[:hoge_id]).order('updated DESC').limit(10)

ここで何をしているかというと、URLから読み取った文字列をActiveRecordに渡して、hoge_idと一致するものを持ってきて更に更新日時が新しい順にし、そして最大10件持ってくるという処理をしています

entries.to_json(:root => false)

説明不要かもですが、みんなだいすきJSONを生成しています。最終的にこいつが結果としてrenderされます

今回はgetしか使っていませんが、もちろんpostupdatedestroyも可能です。 長くなったのでここで終わりにしますが、次回はunicornでデーモン化した話を書きたいです
(ちゃんと次回があればの話だがなっ!)

あ。。。GPUの連載止めてた。。書きます

Androidを久々に書くなど

輪講の準備などでちゃんとかけませんでした。その上輪講発表ボコボコマンだったので、昨日は投げやりでしたorz

写真のコードから現在のJava力を察していただけると幸いです。勉強せんと。。 普通に焦燥感しかない

Androidのコードを真面目に触ったのはAndroid2.X系のやつしかなく、もちろんFragmentなんて存在せず、 フツーにMainAvtivityとかで通信系の処理を(非同期ではなく。今考えれば、それは当時でもバッドプラクティスなんですけど。。)やっちゃってたりしたので、 もう完全に置いて行かれているわけです。てかそもそも最近は動的型付けのやつしか書いていなかったし。。

しかしもう言い訳していられない状況になったので、今日向き合ってみました

そもそもFragmentってなんぞや

Fragment

一番下のレイヤーにActivityがあり、その一個上のレイヤーがFragmentとなります。本当はViewを持たないFragmentとかを作ることが出来るらしいですが、僕はまだそのレベルではないので。。

つまり、Fragmentを複数作っておけば、Activityが1つでも表示する内容をActivityを変えることなく変更することが可能になるわけです。

MainActivityからintentしてSubActivityを呼び出すとかしなくていいわけですね。なんかモダンっぽい ちなみに横からメニューが出てくる系実装をしたければFragmentの利用は必須っぽいので今のうちに慣れておこうと思って勉強しました

今のところガワしか出来ておらんのだけれど。。 まあ色々コードを書くと以下のようなViewが完成します

Android Moc

そのうちちゃんとしたコードをGistであげたいですね(リポジトリ作るほどではないので)

それにしてもAndroidStudioいいわ。ベータ版使っていた時はこれマジで大丈夫か(笑)って思ったときもあったけど

まあちょっと困るとすればCocosIDEと見分けがつかなくなるくらい(同じIntellij IDEAなので)

今使ってるHUGOのテーマ使いづらいところが色々とあるのでそのうちテーマ自作しよう。。
コードのシンタックスハイライト出来ないの致命的だし

帰宅してから更新するスタイルがまだ身についていないorz

もう完全に写真無関係だろっていうね。 でもなんか写真ないと寂しいのでつけております。

やっぱJavaは出来て当たり前の言語なんだよなっていう無言の圧力をヒシヒシと感じながら生活しています。 動的型付けの言語ばっか書いているのイクナイ(って言いながら最近動的型付けばっかなんだけど)

個人的にプログラミング言語習得をするときに守っていることがあって、絶対に最初はフレームワークを使わないっていうことを守っています。(守っているというか心がけています)

まあ色々書きたいことはあるんだけどただの愚痴になってしまうので。。。

1つだけいうとフレームワークありきで言語を学習してしまうと、そのフレームワークしか使えないコピペエンジニアになってしまう危険性が格段に高くなってしまうってことですね。てかそれに尽きると思っています

週末更新出来なかったorz

※写真には特に意味ありません

結局週末更新できなかったorzorzorz
金曜日に久しぶりにある先輩達と飲んで、飲み過ぎて結局朝まで飲んでて、その反動が土曜日に来て一日まともに行動できず、 日曜日の午前中も調子がでなくて起きられず、午後から輪講発表用の資料作成で全部潰れるというつまらない週末を過ごしておりました。

ていうかすごいうんこみたいな生活しているなwまあ事実うんこだから仕方がないw

どうでもいいんですけど、
ThreadSafeなプロセスをThread並列させてもとくに問題ないじゃないですか。当たり前ですけど。だけどThreadSafeなプロセスをThread並列させて、更にProcess並列させた場合、ThreadSafeはちゃんと保証されるんですかね。まあCUDAの話なんですけど。。
なんかCUDAそうじゃないような気がしているんですよね

もう夏バテした感

朝起きたら既に30℃超えていて本格的な夏到来ってかんじですね。僕が小さいことこんなに暑くなること珍しかった気がしますけど、最近では普通になりましたね

久しぶりに何も考えずに文章をだらだら書こうかなと思います。
昔は色々な分野で、自分の考えと違う人たちや、自分が正しいと考えていることとは異なった考えの人たちに対して、自分の立場を説明して、そして自分の考えに同調・行動して欲しいみたいな気持ちが強かったのですが、 今は全然そんなことなくて、むしろみんな色々!多様性!うまく言っていればそれでいいじゃん!みたいな感じて他人に対して 過度に深く知ろうとか、自分の考えを説明しようとかしなくなりました。 これが色々考えた末の結論だと思ってはいるのですが、単純に面倒くさくなっただけだったりして(笑)

まあ面倒くさくなったことも一理あるんですけどね

とりあえず僕は、自分が楽しく生きられていて、ついでに、自分に関係のある身の回りの人が概ね幸せで、楽しく生きられていればそれで良いかなってなっています。
自分ひとりで出来ることには限界が必ずありますから、とりあえず身の丈にあったことをやっていこうと思います

もちろん

身の丈にあった≠成長しない

ではないですよ。
はい、気持ち悪いナルシストポエムの完成〜(ポエムでもねえけどw)