Discover the power of Tensor Cores

Written in C++ and CUDA.
by Satoru Ogura | https://satachito.github.io/TechBLOG/ | Feb 22 2022

Tensor Cores in NVIDIA site

Tensor Cores are units that can perform multiple simple calculations simultaneously, and are said to be especially capable of performing the dense matrix product required in AI. So let's check it out by measuring the time to multiply a 512 x 1024 matrix by a 1024 x 2048 matrix.

All matrices are in Row-major order.
Row-major order

We have placed the complete program at the following address, and here are excerpts from it.
https://github.com/Satachito/matpro

Environment

CPU
Intel(R) Xeon(R) CPU @ 2.80GHz
GPU
A100
GEFORCE RTX 3090
T4

Preparation


#define	M	512
#define	K	1024
#define	N	2048

Using standard C++


void
MatPro( float* a, float* b, float* c ) {
	for ( auto m = 0; m < M; m++ ) {
		for ( auto n = 0; n < N; n++ ) {
			auto $ = 0.;
			for ( auto k = 0; k < K; k++ ) $ += a[ m * K + k ] * b[ k * N + n ];
			c[ m * N + n ] = $;
		}
	}
}

The computation time with this program is about 317,639 μs. With -Ofast option.

Using CUDA Cores


__global__ void
MatPro( float* a, float* b, float* c ) {
	auto $ = 0.;
	auto n = blockIdx.x * blockDim.x + threadIdx.x;
	auto m = blockIdx.y * blockDim.y + threadIdx.y;
	for ( auto k = 0; k < K; k++ ) $ += a[ m * K + k ] * b[ k * K + n ];
	c[ m * N + n ] = $;
}

MatPro<<< dim3( N / 32, M / 32 ), dim3( 32, 32 ) >>>( a, b, c );

The computation time with this program is listed below.
A100RTX 3090T4
1,222μs9,329μs52,495μs

Using Tensor Cores with half precision data.

template < typename F > __global__ void
MatPro(
	const	half*	_a
,	const	half*	_b
,			F*		_c
) {
	wmma::fragment< wmma::matrix_a, 16, 16, 16, half, wmma::row_major > a;
	wmma::fragment< wmma::matrix_b, 16, 16, 16, half, wmma::row_major > b;
	wmma::fragment< wmma::accumulator, 16, 16, 16, F > c;

	wmma::fill_fragment( c, 0 );

	for ( auto k = 0; k < K; k += 16 ) {
		wmma::load_matrix_sync( a, _a + ( blockIdx.y * K * 16 + k ), K );
		wmma::load_matrix_sync( b, _b + ( k * N + blockIdx.x * 16 ), N );
		wmma::mma_sync( c, a, b, c );
	}

	wmma::store_matrix_sync( _c + ( blockIdx.y * N * 16 + blockIdx.x * 16 ), c, N, wmma::mem_row_major );
}

MatPro< F ><<< dim3( N / 16, M / 16 ), 32 >>>( a, b, c );

The computation time with this program is listed below.
In case of result is in single(32bit) precision.
A100RTX 3090T4
547μs472μs2035μs
In case of result is in half(16bit) precision.
A100RTX 3090T4
435μs319μs1,815μs

Conclusion

In computing matrix products, Tensor Cores shows that using half-precision data can save memory and increase computation speed.

Bonus

https://github.com/Satachito/matpro This repository contains sample code that performs matrix products in a variety of ways, including multi-CPU and SIMD (AVX-512).