Automated work group parameters and tiling matmul
This commit is contained in:
parent
8c9ad5f2a4
commit
425380f1a1
3 changed files with 183 additions and 21 deletions
|
|
@ -5,35 +5,64 @@ import numpy as np
|
|||
|
||||
|
||||
class MatMulOp:
|
||||
def __init__(self, manager: kp.Manager, local_size_x: int = 1, local_size_y: int = 1):
|
||||
def __init__(self, manager: kp.Manager, local_size_x: int = -1, local_size_y: int = -1):
|
||||
self.mgr = manager
|
||||
assert(local_size_x > 0)
|
||||
assert(local_size_y > 0)
|
||||
|
||||
props = self.mgr.get_device_properties()
|
||||
max_workgroup_invocation = props['max_work_group_invocations']
|
||||
max_workgroup_size = props['max_work_group_size']
|
||||
if local_size_x < 1:
|
||||
if local_size_y > 0:
|
||||
local_size_x = 1
|
||||
while (2 * local_size_x * local_size_y <= max_workgroup_invocation
|
||||
and 2 * local_size_x <= max_workgroup_size[0]):
|
||||
local_size_x *= 2
|
||||
else:
|
||||
local_size_x = 1
|
||||
local_size_y = 1
|
||||
while 2 * local_size_x * local_size_y <= max_workgroup_invocation:
|
||||
if 2 * local_size_x <= max_workgroup_size[0]:
|
||||
local_size_x *= 2
|
||||
if 2 * local_size_y <= max_workgroup_size[1]:
|
||||
local_size_y *= 2
|
||||
elif 2 * local_size_x > max_workgroup_size[0]: # stop if neither x nor y can be double
|
||||
break
|
||||
elif local_size_y < 0:
|
||||
local_size_y = 1
|
||||
while (2 * local_size_x * local_size_y <= max_workgroup_invocation
|
||||
and 2 * local_size_x <= max_workgroup_size[0]):
|
||||
local_size_y *= 2
|
||||
|
||||
assert local_size_x > 0
|
||||
assert local_size_y > 0
|
||||
assert local_size_x * local_size_y <= max_workgroup_invocation
|
||||
assert local_size_x <= max_workgroup_size[0]
|
||||
assert local_size_y <= max_workgroup_size[1]
|
||||
self.local_size_x = local_size_x
|
||||
self.local_size_y = local_size_y
|
||||
|
||||
self.shader = kp.Shader.compile_source(f'''
|
||||
#version 450
|
||||
#version 450
|
||||
|
||||
layout (local_size_x = {local_size_x}, local_size_y = {local_size_y}) in;
|
||||
layout (local_size_x = {local_size_x}, local_size_y = {local_size_y}) in;
|
||||
|
||||
layout (set = 0, binding = 0) readonly buffer buf_in_tensor_1 {{ float in_tensor_1[]; }};
|
||||
layout (set = 0, binding = 1) readonly buffer buf_in_tensor_2 {{ float in_tensor_2[]; }};
|
||||
layout (set = 0, binding = 2) writeonly buffer buf_out_tensor {{ float out_tensor[]; }};
|
||||
layout (set = 0, binding = 0) readonly buffer buf_in_tensor_1 {{ float in_tensor_1[]; }};
|
||||
layout (set = 0, binding = 1) readonly buffer buf_in_tensor_2 {{ float in_tensor_2[]; }};
|
||||
layout (set = 0, binding = 2) writeonly buffer buf_out_tensor {{ float out_tensor[]; }};
|
||||
|
||||
layout (constant_id = 0) const float tensor_size_f = 0;
|
||||
layout (constant_id = 0) const float tensor_size_f = 0;
|
||||
|
||||
|
||||
void main()
|
||||
{{
|
||||
uint globalRow = gl_GlobalInvocationID.x;
|
||||
uint globalCol = gl_GlobalInvocationID.y;
|
||||
uint tensor_size = uint(tensor_size_f);
|
||||
float acc = 0.0;
|
||||
for(uint k = 0u; k < tensor_size; k++)
|
||||
acc += in_tensor_1[(k * tensor_size) + globalRow] * in_tensor_2[(globalCol * tensor_size) + k];
|
||||
out_tensor[(globalCol * tensor_size) + globalRow] = acc;
|
||||
}}''')
|
||||
void main()
|
||||
{{
|
||||
uint globalRow = gl_GlobalInvocationID.x;
|
||||
uint globalCol = gl_GlobalInvocationID.y;
|
||||
uint tensor_size = uint(tensor_size_f);
|
||||
float acc = 0.0;
|
||||
for(uint k = 0u; k < tensor_size; k++)
|
||||
acc += in_tensor_1[(k * tensor_size) + globalRow] * in_tensor_2[(globalCol * tensor_size) + k];
|
||||
out_tensor[(globalCol * tensor_size) + globalRow] = acc;
|
||||
}}''')
|
||||
self.tensor_shape: tuple[int, int] = (0, 0)
|
||||
self.params: list[kp.Tensor] = []
|
||||
self.algo = None
|
||||
|
|
@ -62,7 +91,7 @@ class MatMulOp:
|
|||
def main():
|
||||
mgr = kp.Manager()
|
||||
|
||||
matmul_op = MatMulOp(mgr, 64, 64)
|
||||
matmul_op = MatMulOp(mgr)
|
||||
|
||||
tensor_size = 512
|
||||
tensor_shape = [tensor_size, tensor_size]
|
||||
|
|
@ -92,5 +121,11 @@ def main():
|
|||
f'{experiment_count * op_count / (1e9 * experiment_time):0.2f}GFLOPS')
|
||||
|
||||
|
||||
def test():
|
||||
main()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
else:
|
||||
test()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue