File size: 3,858 Bytes
32b4893 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 | (* ========================================================================
* SOVEREIGN LEVIATHAN NODE LICENSE
* License-ID: SL-AGPL3-001 | Covenant-Version: 1.0
* Copyright (C) 2026 SnapKittyWest. Ahmad Ali Parr, Bel Esprit D'Accord Irrevocable Trust.
* ========================================================================
*
* This file is a covered work under the GNU Affero General Public License,
* version 3, together with the Sovereign Leviathan additional terms.
*
* Hark, though this node be but a spark,
* Its covenant endureth through the dark.
*
* Ignorantia juris non excusat.
* ======================================================================== *)
{ gpu_host.pas
Pascal host skeleton for launching CUDA kernels via a C shim.
Free Pascal (FPC) compatible.
Lines: ~220
}
program GPUHost;
{$mode objfpc}{$H+}
uses
ctypes, SysUtils;
{ --- Memory manager: simple arena with bookkeeping --- }
type
PBlock = ^TBlock;
TBlock = record
addr: Pointer;
size: NativeUInt;
freed: Boolean;
end;
var
Blocks: array of PBlock;
procedure register_block(p: Pointer; sz: NativeUInt);
var
b: PBlock;
begin
New(b);
b^.addr := p;
b^.size := sz;
b^.freed := False;
SetLength(Blocks, Length(Blocks) + 1);
Blocks[High(Blocks)] := b;
end;
function find_block(p: Pointer): Integer;
var
i: Integer;
begin
for i := 0 to High(Blocks) do
if Blocks[i]^.addr = p then Exit(i);
Result := -1;
end;
procedure check_no_leaks;
var
i: Integer;
begin
for i := 0 to High(Blocks) do
if not Blocks[i]^.freed then
Writeln('Memory leak: block at ', Blocks[i]^.addr, ' size=', Blocks[i]^.size);
end;
{ --- C shim declarations (must match the C shim below) --- }
type
TCUResult = cint;
procedure cuda_init; cdecl; external 'libcuda_shim.so';
procedure cuda_finalize; cdecl; external 'libcuda_shim.so';
function cuda_alloc(size: NativeUInt): Pointer; cdecl; external 'libcuda_shim.so';
procedure cuda_free(p: Pointer); cdecl; external 'libcuda_shim.so';
function cuda_launch_vector_add(a_dev, b_dev, c_dev: Pointer; n: cint): TCUResult; cdecl; external 'libcuda_shim.so';
{ --- Pascal wrappers around the C shim --- }
function host_alloc(size: NativeUInt): Pointer;
begin
Result := cuda_alloc(size);
if Result = nil then
raise Exception.Create('cuda_alloc failed');
register_block(Result, size);
end;
procedure host_free(p: Pointer);
var idx: Integer;
begin
idx := find_block(p);
if idx = -1 then
raise Exception.Create('free: unknown pointer');
if Blocks[idx]^.freed then
raise Exception.Create('double free detected');
Blocks[idx]^.freed := True;
cuda_free(p);
end;
{ --- Test: vector add on GPU --- }
procedure test_vector_add(n: Integer);
var
bytes: NativeUInt;
a_dev, b_dev, c_dev: Pointer;
i: Integer;
hostA, hostB, hostC: PSingle;
res: TCUResult;
begin
bytes := NativeUInt(n) * SizeOf(Single);
a_dev := host_alloc(bytes);
b_dev := host_alloc(bytes);
c_dev := host_alloc(bytes);
{ prepare host buffers (on CPU) and copy via shim if needed; for simplicity we assume shim provides device alloc only and kernel uses device memory }
{ In a real system, add cuda_memcpy_host_to_device and device_to_host functions }
res := cuda_launch_vector_add(a_dev, b_dev, c_dev, n);
if res <> 0 then
Writeln('Kernel launch failed: ', res)
else
Writeln('Kernel launched successfully');
{ cleanup }
host_free(a_dev);
host_free(b_dev);
host_free(c_dev);
end;
{ --- Main --- }
begin
try
Writeln('Initializing CUDA shim...');
cuda_init();
Writeln('Allocating and launching test kernel...');
test_vector_add(1024);
Writeln('Finalizing...');
cuda_finalize();
check_no_leaks();
Writeln('Done.');
except
on E: Exception do
Writeln('Error: ', E.ClassName, ': ', E.Message);
end;
end.
|