krnl 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,147 @@
1
+ import numpy as np
2
+ import pyopencl as cl
3
+ import pyopencl.array as cl_array
4
+ from pyopencl import Program
5
+ from backends.backends.kernels import MATMUL_KERNEL, SIGMOID_KERNEL
6
+
7
+ def get_gpu_info():
8
+ platforms = cl.get_platforms()
9
+ gpu_info = []
10
+
11
+ for platform in platforms:
12
+ devices = platform.get_devices(device_type=cl.device_type.GPU)
13
+ for device in devices:
14
+ info = {
15
+ "platform": platform.name,
16
+ "device": device.name,
17
+ "max_compute_units": device.max_compute_units,
18
+ "max_work_group_size": device.max_work_group_size,
19
+ "global_mem_size": device.global_mem_size,
20
+ "local_mem_size": device.local_mem_size,
21
+ "max_clock_frequency": device.max_clock_frequency,
22
+ }
23
+ gpu_info.append(info)
24
+
25
+ return gpu_info
26
+
27
+ class OpenCLBackend:
28
+ _instance = None
29
+
30
+ @classmethod
31
+ def instance(cls):
32
+ if cls._instance is None:
33
+ cls._instance = cls()
34
+ return cls._instance
35
+
36
+ def __init__(self):
37
+ self.context = cl.create_some_context()
38
+ self.queue = cl.CommandQueue(self.context)
39
+ self.matmul_program = Program(self.context, MATMUL_KERNEL).build()
40
+ self.sigmoid_program = Program(self.context, SIGMOID_KERNEL).build()
41
+
42
+ def upload(self, data):
43
+ data = np.ascontiguousarray(data)
44
+ return cl_array.to_device(self.queue, data)
45
+
46
+ def __add__(self, a: cl_array.Array, b: cl_array.Array):
47
+ if a.shape != b.shape:
48
+ raise ValueError("Tensor shapes must match")
49
+ if a.dtype != b.dtype:
50
+ raise TypeError("Tensor dtypes must match")
51
+ if a.dtype != np.dtype(np.float32):
52
+ raise TypeError("Initial OpenCL backend supports float32 only")
53
+
54
+ result = a + b
55
+
56
+ return result
57
+
58
+ def __mul__(self, a: cl_array.Array, b: cl_array.Array):
59
+ if a.shape != b.shape:
60
+ raise ValueError("Tensor shapes must match")
61
+ if a.dtype != b.dtype:
62
+ raise TypeError("Tensor dtypes must match")
63
+ if a.dtype != np.dtype(np.float32):
64
+ raise TypeError("Initial OpenCL backend supports float32 only")
65
+
66
+ result = a * b
67
+
68
+ return result
69
+
70
+ def __sub__(self, a: cl_array.Array, b: cl_array.Array):
71
+ if a.shape != b.shape:
72
+ raise ValueError("Tensor shapes must match")
73
+ if a.dtype != b.dtype:
74
+ raise TypeError("Tensor dtypes must match")
75
+ if a.dtype != np.dtype(np.float32):
76
+ raise TypeError("Initial OpenCL backend supports float32 only")
77
+
78
+ result = a - b
79
+
80
+ return result
81
+
82
+ def __matmul__(self, a: cl_array.Array, b: cl_array.Array):
83
+ if len(a.shape) != 2 or len(b.shape) != 2:
84
+ raise ValueError("matmul requires two 2D tensors")
85
+
86
+ M, K = a.shape
87
+ K2, N = b.shape
88
+
89
+ if K != K2:
90
+ raise ValueError(
91
+ f"Incompatible shapes for matmul: {a.shape} and {b.shape}"
92
+ )
93
+
94
+ if a.dtype != np.dtype(np.float32) or b.dtype != np.dtype(np.float32):
95
+ raise TypeError("matmul supports float32 only")
96
+
97
+ out = cl_array.empty(
98
+ self.queue,
99
+ (M, N),
100
+ dtype=np.float32
101
+ )
102
+
103
+ self.matmul_program.matmul_f32(
104
+ self.queue,
105
+ (M, N),
106
+ None,
107
+ a.data,
108
+ b.data,
109
+ out.data,
110
+ np.int32(M),
111
+ np.int32(K),
112
+ np.int32(N)
113
+ )
114
+
115
+ def sigmoid(self, input_array: cl_array.Array):
116
+ """
117
+ Apply sigmoid element-wise to a GPU float32 array.
118
+
119
+ sigmoid(x) = 1 / (1 + exp(-x))
120
+ """
121
+
122
+ if not isinstance(input_array, cl_array.Array):
123
+ raise TypeError(
124
+ "sigmoid expects a pyopencl.array.Array"
125
+ )
126
+
127
+ if input_array.dtype != np.dtype(np.float32):
128
+ raise TypeError(
129
+ "sigmoid supports float32 arrays only"
130
+ )
131
+
132
+ output = cl_array.empty_like(input_array)
133
+
134
+ count = np.uint32(input_array.size)
135
+
136
+ self.sigmoid_program.sigmoid_f32(
137
+ self.queue,
138
+ (input_array.size,),
139
+ None,
140
+ input_array.data,
141
+ output.data,
142
+ count,
143
+ )
144
+
145
+ return output
146
+
147
+
@@ -0,0 +1,40 @@
1
+ import platform
2
+ import psutil
3
+ from typing import Literal
4
+ from backends.backends.GPU_processer import get_gpu_info
5
+
6
+
7
+ cpu_freq = psutil.cpu_freq()
8
+ max_clock = cpu_freq.max if cpu_freq else 0
9
+ virtual_mem = psutil.virtual_memory()
10
+
11
+ info = {
12
+ "platform": platform.system(), # e.g., 'Windows', 'Linux', 'Darwin'
13
+ "device": platform.processor(), # e.g., 'Intel64 Family 6 Model...'
14
+ "max_compute_units": psutil.cpu_count(logical=False), # Physical CPU cores
15
+ "max_work_group_size": psutil.cpu_count(logical=True),# Total logical threads
16
+ "global_mem_size": virtual_mem.total, # Total system RAM (bytes)
17
+ "local_mem_size": None, # Placeholder (psutil cannot read CPU L1/L2 cache sizes directly)
18
+ "max_clock_frequency": max_clock # Max clock speed in MHz
19
+ }
20
+
21
+
22
+ class Device(object):
23
+ def __init__(self, device: Literal["CPU", "GPU"], device_id: int = 0):
24
+ self.device = device
25
+ self.device_id = device_id
26
+
27
+ def __repr__(self):
28
+ return f"Device(device={self.device}, device_id={self.device_id})"
29
+
30
+ def get_device_info(self):
31
+ if self.device == "CPU":
32
+ return info
33
+ elif self.device == "GPU":
34
+ gpu_info = get_gpu_info()
35
+ if self.device_id < len(gpu_info):
36
+ return gpu_info[self.device_id]
37
+ else:
38
+ raise ValueError(f"Invalid GPU device_id: {self.device_id}")
39
+ else:
40
+ raise ValueError(f"Invalid device type: {self.device}")
@@ -0,0 +1,37 @@
1
+ MATMUL_KERNEL = """
2
+ __kernel void matmul_f32(
3
+ __global const float *a,
4
+ __global const float *b,
5
+ __global float *c,
6
+ const int M,
7
+ const int K,
8
+ const int N
9
+ )
10
+ {
11
+ int row = get_global_id(0);
12
+ int col = get_global_id(1);
13
+
14
+ if (row < M && col < N) {
15
+ float sum = 0.0f;
16
+
17
+ for (int k = 0; k < K; k++) {
18
+ sum += a[row * K + k] * b[k * N + col];
19
+ }
20
+
21
+ c[row * N + col] = sum;
22
+ }
23
+ }
24
+ """
25
+
26
+ SIGMOID_KERNEL = """
27
+ __kernel void sigmoid_activation(__global const float* input,
28
+ __global float* output,
29
+ const unsigned int count)
30
+ {
31
+ int id = get_global_id(0);
32
+
33
+ if (id < count) {
34
+ output[id] = 1.0f / (1.0f + exp(-input[id]));
35
+ }
36
+ }
37
+ """