in src/c_interface.cpp [154:256]
bool gemm(std::string precision, void *A, void *B, void *C,
bool a_t, bool b_t,
int m, int n, int k,
int lda, int ldb, int ldc,
float alpha, float beta,
CUstream stream, unsigned int grid, unsigned int shared) {
std::string kernel_op = get_op_string(a_t, b_t);
if (grid >= selections[precision][kernel_op].size())
return false;
kernel_properties kp = selections[precision][kernel_op][grid];
if (shared >= kp.shared_sizes.size())
return false;
bool vec4A, vec8A;
bool vec4B, vec8B;
if (a_t) {
vec4A = (lda & 3) == 0 && (m & 3) == 0; //multiple of 4
vec8A = (lda & 7) == 0 && (m & 7) == 0; //multiple of 8
}
else {
vec4A = (lda & 3) == 0 && (k & 3) == 0; //multiple of 4
vec8A = (lda & 7) == 0 && (k & 7) == 0; //multiple of 8
}
if (b_t) {
vec4B = (ldb & 3) == 0 && (k & 3) == 0; //multiple of 4
vec8B = (ldb & 7) == 0 && (k & 7) == 0; //multiple of 8
}
else {
vec4B = (ldb & 3) == 0 && (n & 3) == 0; //multiple of 4
vec8B = (ldb & 7) == 0 && (n & 7) == 0; //multiple of 8
}
bool vec4C = (ldc & 3) == 0 && (n & 3) == 0;
bool vecA = (kp.vA == 4 && vec4A) || (kp.vA == 8 && vec8A);
bool vecB = (kp.vB == 4 && vec4B) || (kp.vB == 8 && vec8B);
bool vecC = kp.vC == 1 || vec4C;
bool vec = vecA && vecB && vecC;
CUdevice device;
int res = cuCtxGetDevice(&device);
if (res != 0)
return false;
bool success;
int major, minor;
std::tie(success, major, minor) = getDeviceProperties(device);
if (success != 0)
return false;
std::string kernel_string;
kernel_string.reserve(64);
kernel_string += precision + "gemm_" + kp.tile_string +
"_" + kernel_op;
if (vec)
kernel_string += "_vec";
if (major == 5)
kernel_string += "_sm_50";
else if (major == 6)
kernel_string += "_sm_60";
else
return false;
auto kernel = kernels_.find(kernel_string);
if (kernel == kernels_.end()) {
loadKernels(major);
kernel = kernels_.find(kernel_string);
}
int blk_A = (m + kp.tile_m - 1) / kp.tile_m;
int blk_B = (n + kp.tile_n - 1) / kp.tile_n;
int blk_a, blk_b;
std::tie(blk_a, blk_A) = closest_divisor(blk_A, kp.div);
std::tie(blk_b, blk_B) = closest_divisor(blk_B, kp.div);
if (blk_a == 1)
std::tie(blk_a, blk_A) = std::make_pair(blk_A, 1);
void *args[13] = {&C, &A, &B, &alpha, &beta, &lda, &ldb, &ldc,
&m, &n, &k, &blk_a, &blk_b};
res = cuLaunchKernel(kernel->second, blk_a * blk_b, blk_B, blk_A,
kp.threads, 1, 1,
kp.shared_sizes[shared], stream, args, NULL);
if (res != 0) {
std::cerr << "Failed to execute " << kernel_string << " " <<
res << std::endl;
return false;
}
return true;
}