LoginSignup
0
1

More than 1 year has passed since last update.

CUDAカーネル内での行列演算

Posted at

CUDAカーネル内で行列やベクトルの演算が必要になった際、コードが複雑になりそうだったため、
以下の部品を作ってみた。動的配列を使いたかったが、メモリ確保に数十ミリ秒を要したため、
静的配列を用いた。このとき、サイズ変更に柔軟に対応するために、サイズをテンプレート引数
として与えるようにした。

いまのところ、メンバ関数は、転置と、掛け算と、3x3の逆行列で、いずれもCUDAカーネル内から
呼ぶことができる。

template<typename T, unsigned int w, unsigned int h> struct K_mat {
	T val[h][w];
	__device__ void transpose(const K_mat<T, h, w>& in) {
		for (unsigned int i = 0; i < h; i++) {
			for (unsigned int j = 0; j < w; j++) {
				val[i][j] = in.val[j][i];
			}
		}
	}
	template<unsigned int d> __device__ void mul(const K_mat<T, d, h>& in0, const K_mat<T, w, d>& in1) {
		for (unsigned int i = 0; i < h; i++) {
			for (unsigned int j = 0; j < w; j++) {
				val[i][j] = 0.0;
				for (unsigned int k = 0; k < d; k++) {
					val[i][j] = val[i][j] + in0.val[i][k] * in1.val[k][j];
				}
			}
		}
	}
	__device__ void inverse_3x3(const K_mat<T, h, w>& in) {
		float det = abs(in.val[0][0] * in.val[1][1] * in.val[2][2]
			          + in.val[0][1] * in.val[1][2] * in.val[2][0]
			          + in.val[0][2] * in.val[2][1] * in.val[1][0]
                      - in.val[0][2] * in.val[1][1] * in.val[2][0]
			          - in.val[0][0] * in.val[2][1] * in.val[1][2]
			          - in.val[0][1] * in.val[1][0] * in.val[2][2]);
		if (1e-7 < det) {  // machine epsilon of 32bit is 1.192e-7
			for (unsigned int i = 0; i < h; i++) {
				for (unsigned int j = 0; j < w; j++) {
					val[i][j] = in.val[(i + 1) % 3][(j + 1) % 3] * in.val[(i + 2) % 3][(j + 2) % 3]
						      - in.val[(i + 2) % 3][(j + 1) % 3] * in.val[(i + 1) % 3][(j + 2) % 3];
					val[i][j] = __fdividef(val[i][j], det);
				}
			}
		}
		else {
			for (unsigned int i = 0; i < h; i++) {
				for (unsigned int j = 0; j < w; j++) {
					val[i][j] = 0.0;
				}
			}
		}
	}
};

なお、上記コードは個人的な勉強のために作成。
(コピペして、機能を適宜追加し、ご自由に使ってください)

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1