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いらないかと持っていたのですが、今後の実装を考えていくうちにどう考えても辛さしかないわって感じになったので速攻で作りました。
個人的にはAWSのAPI 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.erb
をrender
する処理を書いています。ちなみに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
しか使っていませんが、もちろんpost
もupdate
もdestroy
も可能です。
長くなったのでここで終わりにしますが、次回はunicornでデーモン化した話を書きたいです
(ちゃんと次回があればの話だがなっ!)
あ。。。GPUの連載止めてた。。書きます
Androidを久々に書くなど
輪講の準備などでちゃんとかけませんでした。その上輪講発表ボコボコマンだったので、昨日は投げやりでしたorz
写真のコードから現在のJava力を察していただけると幸いです。勉強せんと。。 普通に焦燥感しかない
Androidのコードを真面目に触ったのはAndroid2.X系のやつしかなく、もちろんFragmentなんて存在せず、 フツーにMainAvtivityとかで通信系の処理を(非同期ではなく。今考えれば、それは当時でもバッドプラクティスなんですけど。。)やっちゃってたりしたので、 もう完全に置いて行かれているわけです。てかそもそも最近は動的型付けのやつしか書いていなかったし。。
しかしもう言い訳していられない状況になったので、今日向き合ってみました
そもそもFragmentってなんぞや
一番下のレイヤーにActivityがあり、その一個上のレイヤーがFragmentとなります。本当はViewを持たないFragmentとかを作ることが出来るらしいですが、僕はまだそのレベルではないので。。
つまり、Fragmentを複数作っておけば、Activityが1つでも表示する内容をActivityを変えることなく変更することが可能になるわけです。
MainActivityからintent
してSubActivityを呼び出すとかしなくていいわけですね。なんかモダンっぽい
ちなみに横からメニューが出てくる系実装をしたければFragmentの利用は必須っぽいので今のうちに慣れておこうと思って勉強しました
今のところガワしか出来ておらんのだけれど。。 まあ色々コードを書くと以下のようなViewが完成します
そのうちちゃんとしたコードをGistであげたいですね(リポジトリ作るほどではないので)
それにしてもAndroidStudioいいわ。ベータ版使っていた時はこれマジで大丈夫か(笑)って思ったときもあったけど
まあちょっと困るとすればCocosIDEと見分けがつかなくなるくらい(同じIntellij IDEAなので)
今使ってるHUGOのテーマ使いづらいところが色々とあるのでそのうちテーマ自作しよう。。
コードのシンタックスハイライト出来ないの致命的だし
帰宅してから更新するスタイルがまだ身についていないorz
もう完全に写真無関係だろっていうね。 でもなんか写真ないと寂しいのでつけております。
やっぱJavaは出来て当たり前の言語なんだよなっていう無言の圧力をヒシヒシと感じながら生活しています。 動的型付けの言語ばっか書いているのイクナイ(って言いながら最近動的型付けばっかなんだけど)
個人的にプログラミング言語習得をするときに守っていることがあって、絶対に最初はフレームワークを使わないっていうことを守っています。(守っているというか心がけています)
まあ色々書きたいことはあるんだけどただの愚痴になってしまうので。。。
1つだけいうとフレームワークありきで言語を学習してしまうと、そのフレームワークしか使えないコピペエンジニアになってしまう危険性が格段に高くなってしまうってことですね。てかそれに尽きると思っています
週末更新出来なかったorz
※写真には特に意味ありません
結局週末更新できなかったorzorzorz
金曜日に久しぶりにある先輩達と飲んで、飲み過ぎて結局朝まで飲んでて、その反動が土曜日に来て一日まともに行動できず、
日曜日の午前中も調子がでなくて起きられず、午後から輪講発表用の資料作成で全部潰れるというつまらない週末を過ごしておりました。
ていうかすごいうんこみたいな生活しているなwまあ事実うんこだから仕方がないw
どうでもいいんですけど、
ThreadSafeなプロセスをThread並列させてもとくに問題ないじゃないですか。当たり前ですけど。だけどThreadSafeなプロセスをThread並列させて、更にProcess並列させた場合、ThreadSafeはちゃんと保証されるんですかね。まあCUDAの話なんですけど。。
なんかCUDAそうじゃないような気がしているんですよね
もう夏バテした感
朝起きたら既に30℃超えていて本格的な夏到来ってかんじですね。僕が小さいことこんなに暑くなること珍しかった気がしますけど、最近では普通になりましたね
久しぶりに何も考えずに文章をだらだら書こうかなと思います。
昔は色々な分野で、自分の考えと違う人たちや、自分が正しいと考えていることとは異なった考えの人たちに対して、自分の立場を説明して、そして自分の考えに同調・行動して欲しいみたいな気持ちが強かったのですが、
今は全然そんなことなくて、むしろみんな色々!多様性!うまく言っていればそれでいいじゃん!みたいな感じて他人に対して
過度に深く知ろうとか、自分の考えを説明しようとかしなくなりました。
これが色々考えた末の結論だと思ってはいるのですが、単純に面倒くさくなっただけだったりして(笑)
まあ面倒くさくなったことも一理あるんですけどね
とりあえず僕は、自分が楽しく生きられていて、ついでに、自分に関係のある身の回りの人が概ね幸せで、楽しく生きられていればそれで良いかなってなっています。
自分ひとりで出来ることには限界が必ずありますから、とりあえず身の丈にあったことをやっていこうと思います
もちろん
身の丈にあった≠成長しない
ではないですよ。
はい、気持ち悪いナルシストポエムの完成〜(ポエムでもねえけどw)
Raspberry Piをキオスク化してみた
写真ダウンロードサイトにpixabayという素晴らしいサイトを見つけてしまった。ぱくたそと共にありがたいサイトの一つですね
Raspberry Pi
技術系の話に敏感な人で知らない人はいないんじゃないかと思われるくらい浸透しているRaspberry Piですが、今のところ今すぐ買いたくなるようなメリットを感じられずに結局買っていませんでした。 なんかサーボモーターとかステッピングモーターをつないでいじっている友達は周りにいるのですが、あまりそういうことしないし(笑)
・・・
ひょんなことから、出欠管理の表(Webアプリ)を表示させておきたいという相談をされて、また既にその相談をしてきた友達がraspberry Piを持っていたことから、タイトルのようなことをするに至りました。
僕個人としてはRaspbianってベースはDebianなんだから、update-rc.d
とかでテキトーに起動スクリプト書けばいいんじゃねーとか思っていたのですが、もっと簡単に出来る方法があったので、書きます。
(ちなみにDebianではもうupdate-rc.d
で起動プロセスいじるのは非推奨らしいです。今はinsserv
だそうです。知らんかった)
最初の方針は、
- chromiumの起動スクリプト書く(chromiumというファイル名で保存)
- 書いたスクリプトを
/usr/init.d/
配下に移動 &chmod 755 chromium
sudo update-rc.d chromium Defaults
で登録- ついでにちゃんと登録されているか
sudo find /etc/ -name "*chromium"
で確認
でおkだと思っていたのですが、まあとりあえずうまくいかないので(笑)
次にchromiumがsudo権限で動かないことを知らなくて、ググったとおりにchromiumの起動スクリプトを改変
(具体的には、起動スクリプトの最後らへんに書かれている、exec 〜 "$@"
以下に --user-data-dir
という記述を追加。詳しくは『chromium root実行』などでググるとすぐ出てきます)
をしたものの、やはりうまくいかない。これは困ったなwと思いながらその友達から
パン屋のサイトがめっちゃ簡単そうにやってたよ
と教えてくれたので、教えてもらったこのサイトを見てみると。。
まずパン屋では無いことがわかりましたね(笑)
という僕も最初勘違いして、パン屋に負けたのか。。としばらく凹んでましたけど。。
結論としてはXwindowSystem側のAutoStart設定を利用する形になります。
ホームディレクトリ配下に存在する.config
内部のlxsession/LXDE/
にautostart
ファイルを作成して、
その中にchromiumと書けば解決しました
ちなみにchromiumは全画面かつそのサイトしか表示できないキオスクモードが正式に存在し、コマンドラインから
chromium -kiosk
などとうつとキオスクモードになります。また更に
chromium -kiosk "表示したいサイトのアドレス"
とすればサイト指定で(設定で指定しなくても)キオスクモードを実行できます。既知の人からすれば何今更言ってんだよwwwって情報かもしれませんけど(笑)
Raspberry Piが欲しいかは以前として微妙なままですが、久しぶりによく知らないハードを触って楽しかったです