├── .gitignore ├── C# ├── libs │ └── Cloo.dll ├── bin │ ├── unregister.bat │ └── register.bat ├── ClooWrapperVBA │ ├── Properties │ │ └── AssemblyInfo.cs │ ├── Configuration.cs │ ├── ClooWrapperVBA.csproj │ ├── Platform.cs │ ├── ProgramDevice.cs │ └── Device.cs ├── ClooWrapperVBA.sln └── Installation script.iss ├── Excel ├── OpenCl example.xlsm ├── cl │ ├── FloatMatrixMultiplication.cl │ ├── DoubleMatrixMultiplication.cl │ ├── FloatPerformance.cl │ └── DoublePerformance.cl ├── ProgrammingDevice.cls ├── Configuration.vbs ├── CTimer.cls ├── Helpers.bas ├── Asynchronous.bas ├── HelloWorld.bas ├── Configuration.bas └── Performance.bas └── Readme.md /.gitignore: -------------------------------------------------------------------------------- 1 | .vs 2 | obj 3 | bin 4 | *.obj 5 | *.pdb 6 | *.tlb -------------------------------------------------------------------------------- /C#/libs/Cloo.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Excel-lent/ClooWrapperVBA/HEAD/C#/libs/Cloo.dll -------------------------------------------------------------------------------- /Excel/OpenCl example.xlsm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Excel-lent/ClooWrapperVBA/HEAD/Excel/OpenCl example.xlsm -------------------------------------------------------------------------------- /C#/bin/unregister.bat: -------------------------------------------------------------------------------- 1 | call "%SystemRoot%\Microsoft.NET\Framework\v4.0.30319\RegAsm.exe" /u "ClooWrapperVBA.dll" 2 | call "%SystemRoot%\Microsoft.NET\Framework64\v4.0.30319\RegAsm.exe" /u "ClooWrapperVBA_x64.dll" 3 | set /p=Hit ENTER to continue... -------------------------------------------------------------------------------- /C#/bin/register.bat: -------------------------------------------------------------------------------- 1 | call "%SystemRoot%\Microsoft.NET\Framework\v4.0.30319\RegAsm.exe" "ClooWrapperVBA.dll" /tlb: "ClooWrapperVBA.tlb" /codebase 2 | call "%SystemRoot%\Microsoft.NET\Framework64\v4.0.30319\RegAsm.exe" "ClooWrapperVBA_x64.dll" /tlb: "ClooWrapperVBA_x64.tlb" /codebase 3 | set /p=Hit ENTER to continue... -------------------------------------------------------------------------------- /Excel/cl/FloatMatrixMultiplication.cl: -------------------------------------------------------------------------------- 1 | __kernel void 2 | FloatMatrixMult(__global float* MResp, __global float* M1, __global float* M2, __global int* q) 3 | { 4 | // Vector element index 5 | int i = get_global_id(0); 6 | int j = get_global_id(1); 7 | int p = get_global_size(0); 8 | int r = get_global_size(1); 9 | MResp[i + p * j] = 0; 10 | int QQ = q[0]; 11 | for (int k = 0; k < QQ; k++) 12 | { 13 | MResp[i + p * j] += M1[i + p * k] * M2[k + QQ * j]; 14 | } 15 | } -------------------------------------------------------------------------------- /Excel/cl/DoubleMatrixMultiplication.cl: -------------------------------------------------------------------------------- 1 | __kernel void 2 | DoubleMatrixMult(__global double* MResp, __global double* M1, __global double* M2, __global int* q) 3 | { 4 | // Vector element index 5 | int i = get_global_id(0); 6 | int j = get_global_id(1); 7 | int p = get_global_size(0); 8 | int r = get_global_size(1); 9 | MResp[i + p * j] = 0; 10 | int QQ = q[0]; 11 | for (int k = 0; k < QQ; k++) 12 | { 13 | MResp[i + p * j] += M1[i + p * k] * M2[k + QQ * j]; 14 | } 15 | } -------------------------------------------------------------------------------- /Excel/ProgrammingDevice.cls: -------------------------------------------------------------------------------- 1 | VERSION 1.0 CLASS 2 | BEGIN 3 | MultiUse = -1 'True 4 | END 5 | Attribute VB_Name = "ProgrammingDevice" 6 | Attribute VB_GlobalNameSpace = False 7 | Attribute VB_Creatable = False 8 | Attribute VB_PredeclaredId = False 9 | Attribute VB_Exposed = False 10 | Option Explicit 11 | 12 | Public ProgramDevice As ClooWrapperVBA.ProgramDevice 13 | Public deviceType As String 14 | Public DeviceId As Integer 15 | 16 | Private Sub Class_Initialize() 17 | Set ProgramDevice = New ClooWrapperVBA.ProgramDevice 18 | End Sub 19 | -------------------------------------------------------------------------------- /Excel/cl/FloatPerformance.cl: -------------------------------------------------------------------------------- 1 | #undef MAD_4 2 | #undef MAD_16 3 | #undef MAD_64 4 | 5 | #define MAD_4(x, y) x = y*x+y; y = x*y+x; x = y*x+y; y = x*y+x; 6 | #define MAD_16(x, y) MAD_4(x, y); MAD_4(x, y); MAD_4(x, y); MAD_4(x, y); 7 | #define MAD_64(x, y) MAD_16(x, y); MAD_16(x, y); MAD_16(x, y); MAD_16(x, y); 8 | #define MAD_256(x,y) MAD_64(x, y); MAD_64(x, y); MAD_64(x, y); MAD_64(x, y); 9 | #define MAD_1024(x,y) MAD_256(x, y); MAD_256(x, y); MAD_256(x, y); MAD_256(x, y); 10 | #define MAD_4096(x,y) MAD_1024(x, y); MAD_1024(x, y); MAD_1024(x, y); MAD_1024(x, y); 11 | 12 | __kernel void FloatPerformance(__global float* ptr, float _A) { 13 | float x = _A; 14 | float y = (float)get_local_id(0); 15 | 16 | MAD_1024(x, y); 17 | MAD_1024(x, y); 18 | 19 | ptr[get_global_id(0)] = y; 20 | } -------------------------------------------------------------------------------- /Excel/cl/DoublePerformance.cl: -------------------------------------------------------------------------------- 1 | #if defined(cl_khr_fp64) // Khronos extension available? 2 | #pragma OPENCL EXTENSION cl_khr_fp64 : enable 3 | #elif defined(cl_amd_fp64) // AMD extension available? 4 | #pragma OPENCL EXTENSION cl_amd_fp64 : enable 5 | #endif 6 | 7 | #undef MAD_4 8 | #undef MAD_16 9 | #undef MAD_64 10 | 11 | #define MAD_4(x, y) x = y*x+y; y = x*y+x; x = y*x+y; y = x*y+x; 12 | #define MAD_16(x, y) MAD_4(x, y); MAD_4(x, y); MAD_4(x, y); MAD_4(x, y); 13 | #define MAD_64(x, y) MAD_16(x, y); MAD_16(x, y); MAD_16(x, y); MAD_16(x, y); 14 | #define MAD_256(x,y) MAD_64(x, y); MAD_64(x, y); MAD_64(x, y); MAD_64(x, y); 15 | #define MAD_1024(x,y) MAD_256(x, y); MAD_256(x, y); MAD_256(x, y); MAD_256(x, y); 16 | #define MAD_4096(x,y) MAD_1024(x, y); MAD_1024(x, y); MAD_1024(x, y); MAD_1024(x, y); 17 | 18 | __kernel void DoublePerformance(__global double* ptr, double _A) { 19 | double x = _A; 20 | double y = (double)get_local_id(0); 21 | 22 | MAD_1024(x, y); 23 | MAD_1024(x, y); 24 | 25 | ptr[get_global_id(0)] = y; 26 | } -------------------------------------------------------------------------------- /C#/ClooWrapperVBA/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | // Allgemeine Informationen über eine Assembly werden über die folgenden 5 | // Attribute gesteuert. Ändern Sie diese Attributwerte, um die Informationen zu ändern, 6 | // die einer Assembly zugeordnet sind. 7 | [assembly: AssemblyTitle("ClooWrapperVBA")] 8 | [assembly: AssemblyDescription("")] 9 | [assembly: AssemblyConfiguration("")] 10 | [assembly: AssemblyCompany("")] 11 | [assembly: AssemblyProduct("ClooWrapperVBA")] 12 | [assembly: AssemblyCopyright("Copyright © 2021")] 13 | [assembly: AssemblyTrademark("")] 14 | [assembly: AssemblyCulture("")] 15 | 16 | // Durch Festlegen von ComVisible auf FALSE werden die Typen in dieser Assembly 17 | // für COM-Komponenten unsichtbar. Wenn Sie auf einen Typ in dieser Assembly von 18 | // COM aus zugreifen müssen, sollten Sie das ComVisible-Attribut für diesen Typ auf "True" festlegen. 19 | [assembly: ComVisible(true)] 20 | 21 | // Die folgende GUID bestimmt die ID der Typbibliothek, wenn dieses Projekt für COM verfügbar gemacht wird 22 | [assembly: Guid("9692A233-B9D5-46AC-8AE9-C289A9C3276C")] 23 | 24 | // Versionsinformationen für eine Assembly bestehen aus den folgenden vier Werten: 25 | // 26 | // Hauptversion 27 | // Nebenversion 28 | // Buildnummer 29 | // Revision 30 | // 31 | // Sie können alle Werte angeben oder Standardwerte für die Build- und Revisionsnummern verwenden, 32 | // indem Sie "*" wie unten gezeigt eingeben: 33 | // [assembly: AssemblyVersion("1.0.*")] 34 | [assembly: AssemblyVersion("1.0.0.0")] 35 | [assembly: AssemblyFileVersion("1.0.0.0")] -------------------------------------------------------------------------------- /C#/ClooWrapperVBA/Configuration.cs: -------------------------------------------------------------------------------- 1 | using Cloo; 2 | using System; 3 | using System.Runtime.InteropServices; 4 | 5 | namespace ClooWrapperVBA 6 | { 7 | [ComVisible(true)] 8 | [Guid("EFE81401-D294-4377-832B-1E00AB0AB978")] 9 | [ClassInterface(ClassInterfaceType.AutoDual)] 10 | public class Configuration 11 | { 12 | /// 13 | /// Constructor. 14 | /// 15 | public Configuration() 16 | { 17 | } 18 | 19 | /// 20 | /// Platform. 21 | /// 22 | public Platform Platform = null; 23 | 24 | #region Platform-dependent properties and methods 25 | 26 | /// 27 | /// Returns a number of available platforms. 28 | /// 29 | public int Platforms 30 | { 31 | get 32 | { 33 | return ComputePlatform.Platforms.Count; 34 | } 35 | } 36 | 37 | /// 38 | /// Initialize platform. 39 | /// 40 | /// 0-based platform index. 41 | /// True, if platform was initialized successfully, otherwise false. 42 | public bool SetPlatform(int platformIndex) 43 | { 44 | if (platformIndex < ComputePlatform.Platforms.Count) 45 | { 46 | Platform = new Platform(platformIndex); 47 | return true; 48 | } 49 | else 50 | { 51 | return false; 52 | } 53 | } 54 | 55 | #endregion Platform-dependent properties and methods 56 | } 57 | } -------------------------------------------------------------------------------- /Excel/Configuration.vbs: -------------------------------------------------------------------------------- 1 | Option Explicit 2 | 3 | Dim i, j, result 4 | 5 | ' ------------------------ Configuration: 6 | Dim nPlatforms, nDevices 7 | Dim clooConfiguration, device 8 | 9 | Set clooConfiguration = CreateObject("ClooWrapperVBA.Configuration") 10 | 11 | WScript.Echo "---------------Configuration test" 12 | 13 | nPlatforms = clooConfiguration.Platforms 14 | WScript.Echo "nPlatforms = " + CStr(nPlatforms) 15 | 16 | If nPlatforms = 0 then 17 | WScript.Echo "Something went wrong: No available platforms found!" 18 | Wscript.Quit 19 | End If 20 | 21 | For i = 1 To nPlatforms 22 | result = clooConfiguration.SetPlatform(i - 1) 23 | If result Then 24 | WScript.Echo "Platform " + CStr(i - 1) + ":" 25 | WScript.Echo " PlatformName = " + clooConfiguration.Platform.PlatformName 26 | WScript.Echo " PlatformVendor = " + clooConfiguration.Platform.PlatformVendor 27 | WScript.Echo " Number of devices = " + CStr(clooConfiguration.Platform.Devices) 28 | nDevices = clooConfiguration.Platform.Devices 29 | 30 | For j = 1 To nDevices 31 | result = clooConfiguration.Platform.SetDevice(j - 1) 32 | WScript.Echo " Device " + CStr(j - 1) + ":" 33 | WScript.Echo " DeviceType = " + clooConfiguration.Platform.Device.DeviceType 34 | WScript.Echo " DeviceName = " + clooConfiguration.Platform.Device.DeviceName 35 | WScript.Echo " DeviceVendor = " + clooConfiguration.Platform.Device.DeviceVendor 36 | WScript.Echo " MaxComputeUnits = " + CStr(clooConfiguration.Platform.Device.MaxComputeUnits) 37 | WScript.Echo " DeviceAvailable = " + GetBooleanAsString(clooConfiguration.Platform.Device.DeviceAvailable) 38 | WScript.Echo " CompilerAvailable = " + GetBooleanAsString(clooConfiguration.Platform.Device.CompilerAvailable) 39 | Next 40 | End If 41 | Next 42 | 43 | Function GetBooleanAsString(x) 44 | If x Then 45 | GetBooleanAsString = "true" 46 | Else 47 | GetBooleanAsString = "false" 48 | End If 49 | End Function -------------------------------------------------------------------------------- /C#/ClooWrapperVBA.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.31112.23 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ClooWrapperVBA", "ClooWrapperVBA\ClooWrapperVBA.csproj", "{ECB076B8-80B0-4C71-BC7A-4FFD58275F5C}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Debug|x64 = Debug|x64 12 | Debug|x86 = Debug|x86 13 | Release|Any CPU = Release|Any CPU 14 | Release|x64 = Release|x64 15 | Release|x86 = Release|x86 16 | EndGlobalSection 17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 18 | {ECB076B8-80B0-4C71-BC7A-4FFD58275F5C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 19 | {ECB076B8-80B0-4C71-BC7A-4FFD58275F5C}.Debug|Any CPU.Build.0 = Debug|Any CPU 20 | {ECB076B8-80B0-4C71-BC7A-4FFD58275F5C}.Debug|x64.ActiveCfg = Debug|x64 21 | {ECB076B8-80B0-4C71-BC7A-4FFD58275F5C}.Debug|x64.Build.0 = Debug|x64 22 | {ECB076B8-80B0-4C71-BC7A-4FFD58275F5C}.Debug|x86.ActiveCfg = Debug|x86 23 | {ECB076B8-80B0-4C71-BC7A-4FFD58275F5C}.Debug|x86.Build.0 = Debug|x86 24 | {ECB076B8-80B0-4C71-BC7A-4FFD58275F5C}.Release|Any CPU.ActiveCfg = Release|Any CPU 25 | {ECB076B8-80B0-4C71-BC7A-4FFD58275F5C}.Release|Any CPU.Build.0 = Release|Any CPU 26 | {ECB076B8-80B0-4C71-BC7A-4FFD58275F5C}.Release|x64.ActiveCfg = Release|x64 27 | {ECB076B8-80B0-4C71-BC7A-4FFD58275F5C}.Release|x64.Build.0 = Release|x64 28 | {ECB076B8-80B0-4C71-BC7A-4FFD58275F5C}.Release|x86.ActiveCfg = Release|x86 29 | {ECB076B8-80B0-4C71-BC7A-4FFD58275F5C}.Release|x86.Build.0 = Release|x86 30 | EndGlobalSection 31 | GlobalSection(SolutionProperties) = preSolution 32 | HideSolutionNode = FALSE 33 | EndGlobalSection 34 | GlobalSection(ExtensibilityGlobals) = postSolution 35 | SolutionGuid = {0D7E9AC7-C411-4BDC-A1F9-3AAC8DD86B19} 36 | EndGlobalSection 37 | EndGlobal 38 | -------------------------------------------------------------------------------- /Excel/CTimer.cls: -------------------------------------------------------------------------------- 1 | VERSION 1.0 CLASS 2 | BEGIN 3 | MultiUse = -1 'True 4 | END 5 | Attribute VB_Name = "CTimer" 6 | Attribute VB_GlobalNameSpace = False 7 | Attribute VB_Creatable = False 8 | Attribute VB_PredeclaredId = False 9 | Attribute VB_Exposed = False 10 | Option Explicit 11 | 12 | Private Type LARGE_INTEGER 13 | lowpart As Long 14 | highpart As Long 15 | End Type 16 | 17 | #If VBA7 Then 18 | Private Declare PtrSafe Function QueryPerformanceCounter Lib "kernel32" (lpPerformanceCount As LARGE_INTEGER) As Long 19 | Private Declare PtrSafe Function QueryPerformanceFrequency Lib "kernel32" (lpFrequency As LARGE_INTEGER) As Long 20 | #Else 21 | Private Declare Function QueryPerformanceCounter Lib "kernel32" (lpPerformanceCount As LARGE_INTEGER) As Long 22 | Private Declare Function QueryPerformanceFrequency Lib "kernel32" (lpFrequency As LARGE_INTEGER) As Long 23 | #End If 24 | 25 | Private m_CounterStart As LARGE_INTEGER 26 | Private m_CounterEnd As LARGE_INTEGER 27 | Private m_crFrequency As Double 28 | 29 | Private Const TWO_32 = 4294967296# ' = 256# * 256# * 256# * 256# 30 | 31 | Private Function LI2Double(LI As LARGE_INTEGER) As Double 32 | Dim Low As Double 33 | Low = LI.lowpart 34 | If Low < 0 Then 35 | Low = Low + TWO_32 36 | End If 37 | LI2Double = LI.highpart * TWO_32 + Low 38 | End Function 39 | 40 | Private Sub Class_Initialize() 41 | Dim PerfFrequency As LARGE_INTEGER 42 | QueryPerformanceFrequency PerfFrequency 43 | m_crFrequency = LI2Double(PerfFrequency) 44 | End Sub 45 | 46 | Public Sub StartCounter() 47 | QueryPerformanceCounter m_CounterStart 48 | End Sub 49 | 50 | Property Get TimeElapsed() As Double 51 | Dim crStart As Double 52 | Dim crStop As Double 53 | QueryPerformanceCounter m_CounterEnd 54 | crStart = LI2Double(m_CounterStart) 55 | crStop = LI2Double(m_CounterEnd) 56 | TimeElapsed = 1000# * (crStop - crStart) / m_crFrequency 57 | End Property 58 | -------------------------------------------------------------------------------- /C#/Installation script.iss: -------------------------------------------------------------------------------- 1 | [Setup] 2 | AppName=ClooWrapperVBA 3 | AppVerName=ClooWrapperVBA 4 | DefaultDirName={pf}\ClooWrapperVBA 5 | DefaultGroupName=ClooWrapperVBA 6 | Compression=zip 7 | SolidCompression=yes 8 | SourceDir=.\ 9 | PrivilegesRequired=poweruser 10 | AllowCancelDuringInstall=yes 11 | AllowRootDirectory=no 12 | AllowNoIcons=yes 13 | DisableReadyMemo=no 14 | OutputBaseFilename=ClooWrapperVBA setup 15 | 16 | [Dirs] 17 | Name: "{app}"; Permissions: users-full 18 | Name: "{app}\demo"; Permissions: everyone-full 19 | Name: "{app}\demo\cl"; Permissions: everyone-full 20 | 21 | [Files] 22 | Source: bin\ClooWrapperVBA.dll; DestDir: {app}; Flags: ignoreversion recursesubdirs overwritereadonly; Permissions: everyone-full; 23 | Source: bin\ClooWrapperVBA_x64.dll; DestDir: {app}; Flags: ignoreversion recursesubdirs overwritereadonly; Permissions: everyone-full; 24 | Source: bin\Cloo.dll; DestDir: {app}; Flags: ignoreversion recursesubdirs overwritereadonly; Permissions: everyone-full; 25 | Source: ..\Excel\OpenCl example.xlsm; DestDir: {app}\demo; Flags: ignoreversion recursesubdirs overwritereadonly; Permissions: everyone-full; 26 | Source: ..\Excel\cl\FloatPerformance.cl; DestDir: {app}\demo\cl; Flags: ignoreversion recursesubdirs overwritereadonly; Permissions: everyone-full; 27 | Source: ..\Excel\cl\DoublePerformance.cl; DestDir: {app}\demo\cl; Flags: ignoreversion recursesubdirs overwritereadonly; Permissions: everyone-full; 28 | Source: ..\Excel\cl\FloatMatrixMultiplication.cl; DestDir: {app}\demo\cl; Flags: ignoreversion recursesubdirs overwritereadonly; Permissions: everyone-full; 29 | Source: ..\Excel\cl\DoubleMatrixMultiplication.cl; DestDir: {app}\demo\cl; Flags: ignoreversion recursesubdirs overwritereadonly; Permissions: everyone-full; 30 | Source: ..\Excel\Configuration.vbs; DestDir: {app}\demo; Flags: ignoreversion recursesubdirs overwritereadonly; Permissions: everyone-full; 31 | Source: bin\register.bat; DestDir: {app}; Flags: ignoreversion recursesubdirs overwritereadonly; Permissions: everyone-full; 32 | Source: bin\unregister.bat; DestDir: {app}; Flags: ignoreversion recursesubdirs overwritereadonly; Permissions: everyone-full; 33 | 34 | [Icons] 35 | Name: "{group}\Uninstall"; Filename: "{uninstallexe}"; 36 | 37 | [UninstallDelete] 38 | Type: files; Name: "{app}\ClooWrapperVBA.tlb" 39 | Type: files; Name: "{app}\ClooWrapperVBA_x64.tlb" 40 | 41 | [Run] 42 | Filename: "{dotnet40}\RegAsm.exe"; Parameters: /codebase /tlb ClooWrapperVBA.dll; WorkingDir: {app}; Flags: WaitUntilTerminated; 43 | Filename: "{dotnet4064}\RegAsm.exe"; Parameters: /codebase /tlb ClooWrapperVBA_x64.dll; WorkingDir: {app}; Flags: WaitUntilTerminated; 44 | 45 | [UninstallRun] 46 | Filename: "{dotnet40}\RegAsm.exe"; Parameters: /unregister ClooWrapperVBA.dll; WorkingDir: {app}; 47 | Filename: "{dotnet4064}\RegAsm.exe"; Parameters: /unregister ClooWrapperVBA_x64.dll; WorkingDir: {app}; -------------------------------------------------------------------------------- /Excel/Helpers.bas: -------------------------------------------------------------------------------- 1 | Attribute VB_Name = "Helpers" 2 | Option Explicit 3 | 4 | #If VBA7 Then 5 | Public Declare PtrSafe Sub Sleep Lib "kernel32" (ByVal dwMilliseconds&) 6 | #Else 7 | Public Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds&) 8 | #End If 9 | 10 | Function GetFirstDeviceOfType(progDevices As Collection, deviceTypeToSearch$) As Variant 11 | Dim i% 12 | 13 | Set GetFirstDeviceOfType = Nothing 14 | For i = 1 To progDevices.Count: Do 15 | If progDevices.Item(i).deviceType = deviceTypeToSearch Then 16 | Set GetFirstDeviceOfType = progDevices.Item(i).ProgramDevice 17 | Exit Do 18 | End If 19 | Loop While False: Next i 20 | End Function 21 | 22 | Function CreateDeviceCollection(sources$) 23 | Dim progDevices As New Collection 24 | Dim clooConfiguration As New ClooWrapperVBA.Configuration 25 | Dim i&, j&, cpuCounter&, gpuCounter& 26 | Dim result As Boolean 27 | Dim progDevice As ProgrammingDevice 28 | Dim buildLogs$ 29 | 30 | ' Adding of all CPU and GPU devices to collection. 31 | For i = 1 To clooConfiguration.platforms 32 | result = clooConfiguration.SetPlatform(i - 1) 33 | For j = 1 To clooConfiguration.Platform.Devices 34 | result = clooConfiguration.Platform.SetDevice(j - 1) 35 | 36 | Set progDevice = New ProgrammingDevice 37 | 38 | If clooConfiguration.Platform.device.deviceType = "CPU" Then 39 | result = progDevice.ProgramDevice.Build(sources, "", i - 1, j - 1, cpuCounter, buildLogs) 40 | progDevice.DeviceId = cpuCounter 41 | progDevice.deviceType = "CPU" 42 | If result = True Then cpuCounter = cpuCounter + 1 43 | ElseIf clooConfiguration.Platform.device.deviceType = "GPU" Then 44 | result = progDevice.ProgramDevice.Build(sources, "", i - 1, j - 1, gpuCounter, buildLogs) 45 | progDevice.DeviceId = gpuCounter 46 | progDevice.deviceType = "GPU" 47 | If result = True Then gpuCounter = gpuCounter + 1 48 | Else 49 | result = False 50 | End If 51 | 52 | If result Then 53 | Call progDevices.Add(progDevice) 54 | End If 55 | Next j 56 | Next i 57 | 58 | If cpuCounter + gpuCounter = 0 Then 59 | Set CreateDeviceCollection = Nothing 60 | Else 61 | Set CreateDeviceCollection = progDevices 62 | End If 63 | End Function 64 | 65 | Function MatrixToVectorSingle(m() As Single, maxi As Long, maxj As Long) As Single() 66 | Dim v() As Single 67 | Dim i&, j& 68 | 69 | ReDim v(maxi * maxj - 1) 70 | 71 | For i = 0 To maxi - 1 72 | For j = 0 To maxj - 1 73 | v(i + maxi * j) = m(i, j) 74 | Next j 75 | Next i 76 | 77 | MatrixToVectorSingle = v 78 | End Function 79 | 80 | Function VectorToMatrixSingle(v() As Single, maxi As Long, maxj As Long) As Single() 81 | Dim i&, j& 82 | Dim m() As Single 83 | 84 | ReDim m(maxi - 1, maxj - 1) 85 | 86 | For i = 0 To maxi - 1 87 | For j = 0 To maxj - 1 88 | m(i, j) = v(i + maxi * j) 89 | Next j 90 | Next i 91 | 92 | VectorToMatrixSingle = m 93 | End Function 94 | 95 | Function MatrixToVectorDouble(m() As Double, maxi As Long, maxj As Long) As Double() 96 | Dim v() As Double 97 | Dim i&, j& 98 | 99 | ReDim v(maxi * maxj - 1) 100 | 101 | For i = 0 To maxi - 1 102 | For j = 0 To maxj - 1 103 | v(i + maxi * j) = m(i, j) 104 | Next j 105 | Next i 106 | 107 | MatrixToVectorDouble = v 108 | End Function 109 | 110 | Function VectorToMatrixDouble(v() As Double, maxi As Long, maxj As Long) As Double() 111 | Dim i&, j& 112 | Dim m() As Double 113 | 114 | ReDim m(maxi - 1, maxj - 1) 115 | 116 | For i = 0 To maxi - 1 117 | For j = 0 To maxj - 1 118 | m(i, j) = v(i + maxi * j) 119 | Next j 120 | Next i 121 | 122 | VectorToMatrixDouble = m 123 | End Function 124 | -------------------------------------------------------------------------------- /C#/ClooWrapperVBA/ClooWrapperVBA.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {ECB076B8-80B0-4C71-BC7A-4FFD58275F5C} 8 | Library 9 | Properties 10 | ClooWrapperVBA 11 | ClooWrapperVBA 12 | v4.0 13 | 512 14 | true 15 | 16 | 17 | 18 | true 19 | full 20 | false 21 | ..\bin\ 22 | DEBUG;TRACE 23 | prompt 24 | 4 25 | true 26 | true 27 | false 28 | 29 | 30 | pdbonly 31 | true 32 | ..\bin\ 33 | 34 | 35 | prompt 36 | 3 37 | true 38 | 39 | 40 | true 41 | false 42 | AnyCPU 43 | 44 | 45 | true 46 | bin\x64\Debug\ 47 | DEBUG;TRACE 48 | true 49 | true 50 | full 51 | x64 52 | 7.3 53 | prompt 54 | 55 | 56 | ..\bin\ 57 | true 58 | 59 | 60 | true 61 | 3 62 | true 63 | pdbonly 64 | x64 65 | 7.3 66 | prompt 67 | 68 | 69 | true 70 | bin\x86\Debug\ 71 | DEBUG;TRACE 72 | true 73 | true 74 | full 75 | x86 76 | 7.3 77 | prompt 78 | 79 | 80 | ..\bin\ 81 | true 82 | 83 | 84 | true 85 | 3 86 | true 87 | pdbonly 88 | x86 89 | 7.3 90 | prompt 91 | Auto 92 | 93 | 94 | 95 | False 96 | ..\libs\Cloo.dll 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 | -------------------------------------------------------------------------------- /Excel/Asynchronous.bas: -------------------------------------------------------------------------------- 1 | Attribute VB_Name = "Asynchronous" 2 | Option Explicit 3 | 4 | Const MAX_TASKS = 20 5 | Private Const ARRAY_SIZE = 2000 6 | 7 | ' Thread priority as integer (0 - "Lowest", 1 - "BelowNormal", 2 - "Normal", 3 - "AboveNormal", 4 - "Highest"). 8 | Const THREAD_PRIORITY = 0 9 | 10 | Dim progDevices As Collection 11 | Dim currentTaskId&() 12 | 13 | Dim vecResp!() 14 | Dim wsAsynchronous As Worksheet 15 | Dim globalWorkSize&(1), localWorkSize&(), globalWorkOffset&() 16 | Dim logLine% 17 | Dim currentProgress%, prevProgress%, startedTasks%, finishedTasks% 18 | 19 | Dim result As Boolean 20 | Dim allTasks_Completed As Boolean 21 | 22 | Sub MainLoop() 23 | Dim i% 24 | 25 | ' Infinite loop until all tasks are not completed. 26 | While Not allTasks_Completed 27 | For i = 1 To progDevices.Count 28 | If progDevices.Item(i).ProgramDevice.ExecutionCompleted Then 29 | result = progDevices.Item(i).ProgramDevice.GetMemoryArgument_Single(0, vecResp) ' Extract the results and do something with received data here. 30 | 31 | wsAsynchronous.Cells(logLine, 1) = "Task " & currentTaskId(i) & ", " & progDevices.Item(i).ProgramDevice.deviceType & _ 32 | progDevices.Item(i).DeviceId & ": completed" 33 | logLine = logLine + 1 34 | 35 | finishedTasks = finishedTasks + 1 36 | 37 | ' Start new task 38 | If startedTasks < MAX_TASKS Then 39 | ReDim vecResp(UBound(vecResp)) ' Erase output vector. 40 | result = progDevices.Item(i).ProgramDevice.SetMemoryArgument_Single(0, vecResp) 41 | 42 | ' If you want to use callbacks, than use function below 43 | ' "CPU_Task_Completed" is a function that will obtain the callback. 44 | ' Call progDevices.Item(i).ProgramDevice.ExecuteAsync(globalWorkOffset, globalWorkSize, localWorkSize, THREAD_PRIORITY, AddressOf Asynchronous.CPU_Task_Completed) 45 | 46 | result = progDevices.Item(i).ProgramDevice.ExecuteBackground(globalWorkOffset, globalWorkSize, localWorkSize, THREAD_PRIORITY) 47 | startedTasks = startedTasks + 1 48 | currentTaskId(i) = startedTasks 49 | Else 50 | ' If the maximal number of tasks is reached, then set "ExecutionCompleted" to false to avoid additional outputs. 51 | progDevices.Item(i).ProgramDevice.ExecutionCompleted = False 52 | End If 53 | 54 | If startedTasks = finishedTasks Then 55 | allTasks_Completed = True 56 | End If 57 | End If 58 | Next i 59 | 60 | ' Progress-bar. 61 | wsAsynchronous.Cells(2, prevProgress).Interior.Color = RGB(255, 255, 255) 62 | currentProgress = currentProgress + 1 63 | If currentProgress = 50 Then 64 | currentProgress = 1 65 | End If 66 | prevProgress = currentProgress 67 | wsAsynchronous.Cells(2, currentProgress).Interior.Color = RGB(0, 255, 0) 68 | 69 | DoEvents 70 | Sleep (100) 71 | Wend 72 | 73 | wsAsynchronous.Cells(2, currentProgress).Interior.Color = RGB(255, 255, 255) 74 | 75 | For i = 1 To progDevices.Count 76 | result = progDevices.Item(i).ProgramDevice.ReleaseMemObject(3) 77 | result = progDevices.Item(i).ProgramDevice.ReleaseMemObject(2) 78 | result = progDevices.Item(i).ProgramDevice.ReleaseMemObject(1) 79 | result = progDevices.Item(i).ProgramDevice.ReleaseMemObject(0) 80 | result = progDevices.Item(i).ProgramDevice.ReleaseKernel 81 | result = progDevices.Item(i).ProgramDevice.ReleaseProgram 82 | Next i 83 | End Sub 84 | 85 | Sub RunAsynchronous() 86 | Dim vecM1!(), vecM2!() 87 | Dim vecQ&(1) 88 | Dim i&, j&, p&, q&, r&, nRows& 89 | Dim buildLogs$, sources$ 90 | 91 | Set wsAsynchronous = ThisWorkbook.Worksheets("Asynchronous") 92 | 93 | Open Application.ActiveWorkbook.Path & "\cl\FloatMatrixMultiplication.cl" For Binary As #1 94 | sources = Space$(LOF(1)) 95 | Get #1, , sources 96 | Close #1 97 | 98 | ' Adding of all CPU and GPU devices to collection. 99 | Set progDevices = CreateDeviceCollection(sources) 100 | 101 | If progDevices Is Nothing Then 102 | MsgBox ("No devices found! Something is wrong!") 103 | Exit Sub 104 | End If 105 | 106 | logLine = 7 107 | nRows = wsAsynchronous.Cells(Rows.Count, 1).End(xlUp).Row 108 | wsAsynchronous.Range(wsAsynchronous.Cells(logLine, 1), wsAsynchronous.Cells(nRows, 1)).ClearContents 109 | 110 | p = ARRAY_SIZE: q = ARRAY_SIZE: r = ARRAY_SIZE 111 | 112 | ' Dimensions of matrices: 113 | ReDim vecM1(p * q - 1) 114 | ReDim vecM2(q * r - 1) 115 | ReDim vecResp(p * r - 1) 116 | 117 | Randomize 118 | For i = 0 To p - 1 119 | For j = 0 To q - 1 120 | vecM1(i + p * j) = (Rnd() - 0.5) * 10# 121 | Next j 122 | Next i 123 | 124 | For i = 0 To q - 1 125 | For j = 0 To r - 1 126 | vecM2(i + q * j) = (Rnd() - 0.5) * 10# 127 | Next j 128 | Next i 129 | 130 | globalWorkSize(0) = p 131 | globalWorkSize(1) = r 132 | vecQ(0) = q 133 | 134 | ReDim currentTaskId(progDevices.Count) 135 | For i = 1 To progDevices.Count 136 | result = progDevices.Item(i).ProgramDevice.CreateKernel("FloatMatrixMult") 137 | result = progDevices.Item(i).ProgramDevice.SetMemoryArgument_Single(0, vecResp) 138 | result = progDevices.Item(i).ProgramDevice.SetMemoryArgument_Single(1, vecM1) 139 | result = progDevices.Item(i).ProgramDevice.SetMemoryArgument_Single(2, vecM2) 140 | result = progDevices.Item(i).ProgramDevice.SetMemoryArgument_Long(3, vecQ) 141 | Next i 142 | 143 | startedTasks = 0 144 | ' Start execution on all found devices almost simultaneously. 145 | For i = 1 To progDevices.Count 146 | result = progDevices.Item(i).ProgramDevice.ExecuteBackground(globalWorkOffset, globalWorkSize, localWorkSize, THREAD_PRIORITY) 147 | 148 | ' If you want to use callbacks, than use function below 149 | ' "CPU_Task_Completed" is a function that will obtain the callback. 150 | ' Call progDevices.Item(i).ProgramDevice.ExecuteAsync(globalWorkOffset, globalWorkSize, localWorkSize, THREAD_PRIORITY, AddressOf Asynchronous.CPU_Task_Completed) 151 | 152 | startedTasks = startedTasks + 1 153 | currentTaskId(i) = startedTasks 154 | Next i 155 | 156 | prevProgress = 1 157 | currentProgress = 2 158 | allTasks_Completed = False 159 | finishedTasks = 0 160 | 161 | Call MainLoop 162 | End Sub 163 | 164 | 'Sub CPU_Task_Completed() 165 | ' 166 | 'End Sub 167 | -------------------------------------------------------------------------------- /C#/ClooWrapperVBA/Platform.cs: -------------------------------------------------------------------------------- 1 | using Cloo; 2 | using System; 3 | using System.ComponentModel; 4 | using System.Runtime.InteropServices; 5 | using System.Windows.Forms; 6 | 7 | namespace ClooWrapperVBA 8 | { 9 | [ComVisible(true)] 10 | [Guid("88ADB708-A83B-4A5A-8CB0-F3B708E32C1A")] 11 | [InterfaceType(ComInterfaceType.InterfaceIsIDispatch)] 12 | public interface IPlatform 13 | { 14 | /// 15 | /// Returns a name of selected platform. 16 | /// 17 | [DispId(1), Description("Returns a name of selected platform.")] 18 | string PlatformName { get; } 19 | 20 | /// 21 | /// Returns a profile of selected platform. 22 | /// 23 | [DispId(2), Description("Returns a profile of selected platform.")] 24 | string PlatformProfile { get; } 25 | 26 | /// 27 | /// Returns a vendor of selected platform. 28 | /// 29 | [DispId(3), Description("Returns a vendor of selected platform.")] 30 | string PlatformVendor { get; } 31 | 32 | /// 33 | /// Returns an OpenCl version of selected platform. 34 | /// 35 | [DispId(4), Description("Returns an OpenCl version of selected platform.")] 36 | string PlatformVersion { get; } 37 | 38 | /// 39 | /// Returns extensions of selected platform. 40 | /// 41 | [DispId(5), Description("Returns extensions of selected platform.")] 42 | string[] PlatformExtensions { get; } 43 | 44 | /// 45 | /// Returns number of devices available for platformIndex. 46 | /// 47 | [DispId(6), Description("Returns number of devices available for platformIndex.")] 48 | int Devices { get; } 49 | 50 | /// 51 | /// Initialize device. 52 | /// 53 | /// 0-based device index. 54 | /// True, if device was initialized successfully, otherwise false. 55 | [DispId(7), Description("Device initialization.")] 56 | bool SetDevice(int deviceIndex); 57 | 58 | /// 59 | /// Error message. 60 | /// 61 | [DispId(8), Description("Error message.")] 62 | string ErrorMessage { get; set; } 63 | 64 | /// 65 | /// Reference to device. 66 | /// 67 | [DispId(9), Description("Reference to device.")] 68 | Device Device { get; set; } 69 | } 70 | 71 | [Guid("7C0C3E18-6ECD-47C5-9BFD-92035099DA33")] 72 | [ClassInterface(ClassInterfaceType.None)] 73 | [ComVisible(true)] 74 | public class Platform : IPlatform 75 | { 76 | private readonly int platformIndex = -1; 77 | 78 | /// 79 | /// Constructor. 80 | /// 81 | public Platform() 82 | { 83 | } 84 | 85 | /// 86 | /// Constructor. Initializes platform. 87 | /// 88 | /// 0-based platform index. 89 | public Platform(int platformIndex) 90 | { 91 | this.platformIndex = platformIndex; 92 | } 93 | 94 | /// 95 | /// Returns a name of selected platform. 96 | /// 97 | public string PlatformName 98 | { 99 | get 100 | { 101 | try 102 | { 103 | return ComputePlatform.Platforms[platformIndex].Name; 104 | } 105 | catch (Exception ex) 106 | { 107 | ErrorMessage = ex.Message; 108 | return ""; 109 | } 110 | } 111 | } 112 | 113 | /// 114 | /// Returns a profile of selected platform. 115 | /// 116 | public string PlatformProfile 117 | { 118 | get 119 | { 120 | try 121 | { 122 | return ComputePlatform.Platforms[platformIndex].Profile; 123 | } 124 | catch (Exception ex) 125 | { 126 | ErrorMessage = ex.Message; 127 | return ""; 128 | } 129 | } 130 | } 131 | 132 | /// 133 | /// Returns a vendor of selected platform. 134 | /// 135 | public string PlatformVendor 136 | { 137 | get 138 | { 139 | try 140 | { 141 | return ComputePlatform.Platforms[platformIndex].Vendor; 142 | } 143 | catch (Exception ex) 144 | { 145 | ErrorMessage = ex.Message; 146 | return ""; 147 | } 148 | } 149 | } 150 | 151 | /// 152 | /// Returns an OpenCl version of selected platform. 153 | /// 154 | public string PlatformVersion 155 | { 156 | get 157 | { 158 | try 159 | { 160 | return ComputePlatform.Platforms[platformIndex].Version; 161 | } 162 | catch (Exception ex) 163 | { 164 | ErrorMessage = ex.Message; 165 | return ""; 166 | } 167 | } 168 | } 169 | 170 | /// 171 | /// Returns extensions of selected platform. 172 | /// 173 | public string[] PlatformExtensions 174 | { 175 | get 176 | { 177 | if (platformIndex < 0) 178 | { 179 | MessageBox.Show(ErrorMessage); 180 | return null; 181 | } 182 | else 183 | { 184 | string[] tmpStrings; 185 | if (ComputePlatform.Platforms[platformIndex].Extensions.Count == 0) 186 | { 187 | tmpStrings = new string[1]; 188 | } 189 | else 190 | { 191 | tmpStrings = new string[ComputePlatform.Platforms[platformIndex].Extensions.Count]; 192 | ComputePlatform.Platforms[platformIndex].Extensions.CopyTo(tmpStrings, 0); 193 | } 194 | 195 | return tmpStrings; 196 | } 197 | } 198 | } 199 | 200 | /// 201 | /// Returns number of devices available for platformIndex. 202 | /// 203 | public int Devices 204 | { 205 | get 206 | { 207 | return ComputePlatform.Platforms[platformIndex].Devices.Count; 208 | } 209 | } 210 | 211 | /// 212 | /// Initialize device. 213 | /// 214 | /// 0-based device index. 215 | /// True, if device was initialized successfully, otherwise false. 216 | public bool SetDevice(int deviceIndex) 217 | { 218 | if (platformIndex < ComputePlatform.Platforms.Count && deviceIndex < ComputePlatform.Platforms[platformIndex].Devices.Count) 219 | { 220 | Device = new Device(platformIndex, deviceIndex); 221 | return true; 222 | } 223 | else 224 | { 225 | return false; 226 | } 227 | } 228 | 229 | /// 230 | /// Error message. 231 | /// 232 | public string ErrorMessage { get; set; } 233 | 234 | /// 235 | /// Device. 236 | /// 237 | public Device Device { get; set; } = null; 238 | } 239 | } -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 | # COM-wrapper of [Cloo](https://github.com/clSharp/Cloo) to execute OpenCL code from Excel. 2 | [![Download ClooWrapperVBA](https://img.shields.io/sourceforge/dm/cloowrappervba.svg)](https://sourceforge.net/projects/cloowrappervba/files/latest/download) 3 | 4 | The wrapper allows to execute OpenCL code on CPU and GPU devices from VBA. 5 | More detailed description with examples can be found in [my CodeProject article](https://www.codeproject.com/Articles/5332060/How-to-Use-GPU-in-VBA-Excel). 6 | 7 | The wrapper has simple implementation and divided in two independent parts: 8 | -

ClooWrapperVBA.Configuration, to obtain configuration of available platforms and associated CPUs and GPUs.

9 | -

ClooWrapperVBA.ProgramDevice, to compile and start OpenCL programs on CPUs and GPUs and obtain the results. It is also possible to start programs on CPUs and GPUs simultaneously (asynchronously). In asynchronous mode it is also possible to set the priority of execution.

10 |
11 | 12 | ## Downloads 13 | The current version can be downloaded as: 14 | * [Installer for Windows](https://sourceforge.net/projects/cloowrappervba/files/ClooWrapperVBA%20setup.exe/download). Installation path is "C:\Program Files (x86)\ClooWrapperVBA\". 15 | * [Zip-file which contains the same content as the installer](https://sourceforge.net/projects/cloowrappervba/files/ClooWrapperVBA.zip/download). The components must be registered using "register.bat". Please note, that the "register.bat" must be started with admin rights. 16 | 17 |

Directory "demo" contains the Excel table with all demos and VBscript file to check available platforms and devices even without Excel.

18 |
19 | 20 | ## Dependencies 21 | * .Net framework version 4.0. 22 |
23 | 24 | ## Available functions. 25 | * ClooWrapperVBA.Configuration: 26 | *

ClooWrapperVBA.Configuration.Platform - contains information on the available platform.

27 | *

ClooWrapperVBA.Configuration.Platform.Device - contains information on each device in available platforms. In total you can obtain 59 device-specific properties.

28 | 29 | 30 | * ClooWrapperVBA.ProgramDevice: 31 | *

ClooWrapperVBA.ProgramDevice.Build - compiles sources for selected device.

32 | *

ClooWrapperVBA.ProgramDevice.CreateKernel - Loads the function to execute.

33 | *

ClooWrapperVBA.ProgramDevice.SetValueArgument_..., ClooWrapperVBA.ProgramDevice.SetMemoryArgument_... - Sets argument values and arrays of integers, floats and doubles of the function to execute. The parameter "argument_index" starts with 0 for first argument and must be manually incrased for the next arguments. It is also very important to set variables in a right sequence. First, the variable with argument index 0, then with argument index 1 and so on.

34 | *

ClooWrapperVBA.ProgramDevice.ExecuteSync - Execute function synchronously. Excel will move further only after execution was completed.

35 | *

ClooWrapperVBA.ProgramDevice.ExecuteAsync - Start execution of the function asynchronously. The callback function will be called at the end of execution.

36 | *

ClooWrapperVBA.ProgramDevice.ExecuteBackground - Start execution of the function asynchronously. After execution the flag "ClooWrapperVBA.ProgramDevice.ExecutionCompleted" is set to true.

37 | *

ClooWrapperVBA.ProgramDevice.GetMemoryArgument_... - Read arguments (results) from the function.

38 | *

ClooWrapperVBA.ProgramDevice.ReleaseMemObject - Releases instantiated memory objects. The single parameter has the same meaning as "argument_index" from SetValue/MemoryArguments. It should start with highest used "argument_index".

39 | *

ClooWrapperVBA.ProgramDevice.ReleaseKernel and ClooWrapperVBA.ProgramDevice.ReleaseProgram do the rest of disposing of instantiated OpenCL parts.

40 |
41 | 42 | ## VBA samples. 43 | 1. "Configuration": Prints configuration of all platforms and available devices. 44 | 2. "Performance": 45 | - "VBA performance test" uses multiplication of two 1200x1200 matrices and measures execution times. Also, the correctness of results of matrix multiplications on CPU/GPU is compared to VBA results (column "C"). 46 | - The CL code of performance measurements is taken from a CodeProject article "[How to Use Your GPU in .NET](https://www.codeproject.com/Articles/1116907/How-to-Use-Your-GPU-in-NET)". 47 | 3.

"Asynchronous": For asynchronous execution example a matrix multiplication of two 2000x2000 matrices is used.

48 |
49 | 50 | ## VBscript sample. 51 | **Good news**: Yes! It is also possible to use the wrapper also from VBscript! 52 |
53 | **Bad news**: You can obtain only configuration of the platforms and devices. The reason: VBscript uses variants for arrays. Of course it is possible to use object or ArrayList to set the arrays, but this will make the wrapper much complicated and is out of the scope of the wrapper. 54 |
55 | 56 | ## Helpful VBA functions. 57 | - CTimer class is taken from the article "[How do you test running time of VBA code?](https://stackoverflow.com/questions/198409/how-do-you-test-running-time-of-vba-code)". It implements a very precise timer to measure performance. 58 | -

"MatrixToVector" and "VectorToMatrix" are used as expected from their names to load arrays to CPU/GPU and get the results of execution back to VBA in matrix form.

59 |
60 | 61 | ## Implementation notes: 62 | 1. Cloo version 0.9.1.0 is used. The reason: the wrapper was intended to work with version 4.0 of .Net framework. 63 | 2. **Build**: Parameters "deviceIndex", "deviceTypeIndex" have different meaning. 64 | -

"deviceIndex" is a device index of devices at platform defined in "platformIndex". The devices corresponding to each "deviceIndex" can be of different type ("CPU"/"GPU").

65 | - "deviceTypeIndex" is an index inside of same device type. 66 | -

Example: If your platform have 3 devices, one CPU and two GPUs, then the possible "deviceIndex" values are 0 (GPU), 1 (CPU) and 2 (GPU). The "deviceTypeIndex" in this configuration will be 0 and 1 for GPUs and 0 for CPU. You can obtain the sequence of devices using the Configuration.

67 | -

To simplify usage from VBA, all devices can be added to the collection using function "CreateDeviceCollection". You can obtain the first CPU and first GPU using a function "GetFirstDeviceOfType" where the first argument is a collection of devices and the second argument is a device type, "CPU" or "GPU". The collection of all available devices is also very useful to run your code in asynchronous mode at all available devices.

68 | 3. **Build**: Parameter "options" contain compiler options. In simplest case it can be empty ("", not "null" or "Nothing"). Among the common compiler oprions, like "-w" (inhibit all warning messages), you can also define here commonly used constants ("-D name=definition") and use them in the OpenCL code. The complete list of compiler options can be found at [official Khronos home page](https://www.khronos.org/registry/OpenCL/sdk/1.0/docs/man/xhtml/clBuildProgram.html). 69 | 4. **ExecuteAsync** function must be used with care: 70 | -

During debugging Excel can crash because of simultaneous execution of the code in callback and "MainLoop" functions.

71 | -

Writing out of the results to the cells in callback function can also cause an Excel crash.

72 | - A good solution is to use instead **ExecuteBackground** function. 73 | 5. ReleaseMemObject, ReleaseKernel and ReleaseProgram are added to accurately dispose instantiated OpenCL objects and to avoid side effects from not disposed objects. Nevertheless, the current code in Excel example works correctly also without them. 74 |
75 | 76 | ## Not tested parts: 77 | -

globalWorkOffset, localWorkSize were not tested and were added analogously to globalWorkSize.

78 | 79 | ## FAQ: 80 | 1. Configuration: No platforms/devices were found. 81 | - Reason: GPU is detected, Intel CPU not. 82 | - Solution: [Install the OpenCL runtimes for CPU](https://www.intel.com/content/www/us/en/developer/articles/technical/intel-cpu-runtime-for-opencl-applications-with-sycl-support.html). In my case (i5-1035G4), I had to download [2024.2 Release](https://registrationcenter-download.intel.com/akdlm/IRC_NAS/d9883ab0-0e26-47fd-9612-950b95460d72/w_opencl_runtime_p_2024.2.0.980.exe). 83 | - Reason: OpenCL.dll is not found in "Windows" folder. 84 | - Solution: Get OpenCL.dll from other computer. 85 | - Reason: The GPGPU / CPU drivers are too old and not supported by OpenCL. 86 | - Update the drivers. 87 |
88 | 89 | ## SAST Tools 90 | 91 | [PVS-Studio](https://pvs-studio.com/pvs-studio/?utm_source=website&utm_medium=github&utm_campaign=open_source) - static analyzer for C, C++, C#, and Java code. 92 | -------------------------------------------------------------------------------- /Excel/HelloWorld.bas: -------------------------------------------------------------------------------- 1 | Attribute VB_Name = "HelloWorld" 2 | Option Explicit 3 | 4 | Sub HelloWorld() 5 | Dim wsHelloWorld As Worksheet 6 | Dim nRows%, currentRow&, nPlatforms&, nDevices&, i&, j&, result As Boolean 7 | Dim deviceType$, platformName$, platformVendor$, platformVersion$, deviceVendor$, deviceVersion$, driverVersion$, openCLCVersionString$ 8 | Dim maxComputeUnits&, globalMemorySize#, maxClockFrequency#, maxMemoryAllocationSize#, deviceName$, sources$, cpuCounter&, gpuCounter& 9 | Dim buildLogs$, platformId&, DeviceId&, errorString$ 10 | Dim deviceAvailable As Boolean, compilerAvailable As Boolean 11 | Dim m1!(1, 1), m2!(1, 1), vecM1!(), vecM2!(), vecQ&(0), vecResp!(3), globalWorkOffset&(), globalWorkSize&(1), localWorkSize&() 12 | Dim p&, q&, r&, resp!() 13 | 14 | Dim clooConfiguration As New ClooWrapperVBA.Configuration 15 | Dim progDevice As ClooWrapperVBA.ProgramDevice 16 | 17 | Set wsHelloWorld = ThisWorkbook.Worksheets("Hello World!") 18 | 19 | ' Cleanup. 20 | nRows = wsHelloWorld.Cells(Rows.Count, 4).End(xlUp).Row 21 | If nRows >= 2 Then 22 | wsHelloWorld.Range(wsHelloWorld.Cells(2, 4), wsHelloWorld.Cells(nRows, 4)).ClearContents 23 | End If 24 | 25 | ' Read configuration. 26 | nPlatforms = clooConfiguration.platforms 27 | 28 | currentRow = 2 29 | For i = 1 To nPlatforms 30 | result = clooConfiguration.SetPlatform(i - 1) 31 | If result Then 32 | platformName = clooConfiguration.Platform.platformName 33 | platformVendor = clooConfiguration.Platform.platformVendor 34 | platformVersion = clooConfiguration.Platform.platformVersion 35 | 36 | wsHelloWorld.Cells(currentRow, 1) = "Platform": wsHelloWorld.Cells(currentRow, 2) = i - 1: currentRow = currentRow + 1 37 | wsHelloWorld.Cells(currentRow, 2) = "Name": wsHelloWorld.Cells(currentRow, 2) = platformName: currentRow = currentRow + 1 38 | wsHelloWorld.Cells(currentRow, 2) = "Vendor": wsHelloWorld.Cells(currentRow, 3) = platformVendor: currentRow = currentRow + 1 39 | wsHelloWorld.Cells(currentRow, 2) = "Version": wsHelloWorld.Cells(currentRow, 3) = platformVersion: currentRow = currentRow + 1 40 | 41 | nDevices = clooConfiguration.Platform.Devices 42 | For j = 1 To nDevices 43 | result = clooConfiguration.Platform.SetDevice(j - 1) 44 | 45 | If result Then 46 | deviceType = clooConfiguration.Platform.device.deviceType 47 | deviceName = clooConfiguration.Platform.device.deviceName 48 | deviceVendor = clooConfiguration.Platform.device.deviceVendor 49 | maxComputeUnits = clooConfiguration.Platform.device.maxComputeUnits 50 | deviceAvailable = clooConfiguration.Platform.device.deviceAvailable 51 | compilerAvailable = clooConfiguration.Platform.device.compilerAvailable 52 | deviceVersion = clooConfiguration.Platform.device.deviceVersion 53 | driverVersion = clooConfiguration.Platform.device.driverVersion 54 | globalMemorySize = clooConfiguration.Platform.device.globalMemorySize 55 | maxClockFrequency = clooConfiguration.Platform.device.maxClockFrequency 56 | maxMemoryAllocationSize = clooConfiguration.Platform.device.maxMemoryAllocationSize 57 | openCLCVersionString = clooConfiguration.Platform.device.openCLCVersionString 58 | 59 | wsHelloWorld.Cells(currentRow, 2) = "Device": wsHelloWorld.Cells(currentRow, 3) = j - 1: currentRow = currentRow + 1 60 | wsHelloWorld.Cells(currentRow, 3) = "Type": wsHelloWorld.Cells(currentRow, 4) = deviceType: currentRow = currentRow + 1 61 | wsHelloWorld.Cells(currentRow, 3) = "Name": wsHelloWorld.Cells(currentRow, 4) = deviceName: currentRow = currentRow + 1 62 | wsHelloWorld.Cells(currentRow, 3) = "Vendor": wsHelloWorld.Cells(currentRow, 4) = deviceVendor: currentRow = currentRow + 1 63 | wsHelloWorld.Cells(currentRow, 3) = "MaxComputeUnits": wsHelloWorld.Cells(currentRow, 4) = maxComputeUnits: currentRow = currentRow + 1 64 | wsHelloWorld.Cells(currentRow, 3) = "DeviceAvailable": wsHelloWorld.Cells(currentRow, 4) = deviceAvailable: currentRow = currentRow + 1 65 | wsHelloWorld.Cells(currentRow, 3) = "CompilerAvailable": wsHelloWorld.Cells(currentRow, 4) = compilerAvailable: currentRow = currentRow + 1 66 | wsHelloWorld.Cells(currentRow, 3) = "DeviceVersion": wsHelloWorld.Cells(currentRow, 4) = deviceVersion: currentRow = currentRow + 1 67 | wsHelloWorld.Cells(currentRow, 3) = "DriverVersion": wsHelloWorld.Cells(currentRow, 4) = driverVersion: currentRow = currentRow + 1 68 | wsHelloWorld.Cells(currentRow, 3) = "GlobalMemorySize, bytes": wsHelloWorld.Cells(currentRow, 4) = globalMemorySize: currentRow = currentRow + 1 69 | wsHelloWorld.Cells(currentRow, 3) = "MaxClockFrequency, MHz": wsHelloWorld.Cells(currentRow, 4) = maxClockFrequency: currentRow = currentRow + 1 70 | wsHelloWorld.Cells(currentRow, 3) = "MaxMemoryAllocationSize, bytes": wsHelloWorld.Cells(currentRow, 4) = maxMemoryAllocationSize: currentRow = currentRow + 1 71 | wsHelloWorld.Cells(currentRow, 3) = "OpenCLCVersionString": wsHelloWorld.Cells(currentRow, 4) = openCLCVersionString: currentRow = currentRow + 1 72 | End If 73 | Next j 74 | End If 75 | Next i 76 | 77 | ' Multiplication of two matrices. 78 | ' Read the OpenCL sources. 79 | Open Application.ActiveWorkbook.Path & "\cl\FloatMatrixMultiplication.cl" For Binary As #1 80 | sources = Space$(LOF(1)) 81 | Get #1, , sources 82 | Close #1 83 | 84 | ' Find the first found device that can compile the code. 85 | platformId = 0 86 | Do While platformId <= clooConfiguration.platforms - 1 87 | result = clooConfiguration.SetPlatform(platformId) 88 | cpuCounter = 0 89 | gpuCounter = 0 90 | For DeviceId = 0 To clooConfiguration.Platform.Devices - 1 91 | result = clooConfiguration.Platform.SetDevice(DeviceId) 92 | 93 | If clooConfiguration.Platform.device.compilerAvailable Then 94 | If clooConfiguration.Platform.device.deviceType = "CPU" Then 95 | Set progDevice = New ClooWrapperVBA.ProgramDevice 96 | result = progDevice.Build(sources, "", platformId, DeviceId, cpuCounter, buildLogs) 97 | If result Then 98 | Exit Do 99 | Else 100 | cpuCounter = cpuCounter + 1 101 | End If 102 | End If 103 | If clooConfiguration.Platform.device.deviceType = "GPU" Then 104 | Set progDevice = New ClooWrapperVBA.ProgramDevice 105 | result = progDevice.Build(sources, "", platformId, DeviceId, gpuCounter, buildLogs) 106 | gpuCounter = gpuCounter + 1 107 | If result Then 108 | Exit Do 109 | Else 110 | gpuCounter = gpuCounter + 1 111 | End If 112 | End If 113 | End If 114 | Next DeviceId 115 | platformId = platformId + 1 116 | Loop 117 | 118 | errorString = progDevice.errorString 119 | result = progDevice.CreateKernel("FloatMatrixMult") 120 | 121 | ' Initialization of arrays: 122 | p = 2: q = 2: r = 2 123 | For i = 0 To p - 1 124 | For j = 0 To q - 1 125 | m1(i, j) = wsHelloWorld.Cells(i + 1, j + 7) 126 | Next j 127 | Next i 128 | vecM1 = MatrixToVectorSingle(m1, p, q) 129 | For i = 0 To q - 1 130 | For j = 0 To r - 1 131 | m2(i, j) = wsHelloWorld.Cells(i + 3, j + 7) 132 | Next j 133 | Next i 134 | vecM2 = MatrixToVectorSingle(m2, q, r) 135 | vecQ(0) = q 136 | 137 | result = progDevice.SetMemoryArgument_Single(0, vecResp) 138 | result = progDevice.SetMemoryArgument_Single(1, vecM1) 139 | result = progDevice.SetMemoryArgument_Single(2, vecM2) 140 | result = progDevice.SetMemoryArgument_Long(3, vecQ) 141 | 142 | globalWorkSize(0) = p 143 | globalWorkSize(1) = r 144 | 145 | result = progDevice.ExecuteSync(globalWorkOffset, globalWorkSize, localWorkSize) 146 | 147 | result = progDevice.GetMemoryArgument_Single(0, vecResp) 148 | 149 | resp = VectorToMatrixSingle(vecResp, p, r) 150 | 151 | For i = 0 To p - 1 152 | For j = 0 To r - 1 153 | wsHelloWorld.Cells(i + 5, j + 7) = resp(i, j) 154 | Next j 155 | Next i 156 | 157 | result = progDevice.ReleaseMemObject(3) 158 | result = progDevice.ReleaseMemObject(2) 159 | result = progDevice.ReleaseMemObject(1) 160 | result = progDevice.ReleaseMemObject(0) 161 | result = progDevice.ReleaseKernel 162 | result = progDevice.ReleaseProgram 163 | End Sub 164 | -------------------------------------------------------------------------------- /Excel/Configuration.bas: -------------------------------------------------------------------------------- 1 | Attribute VB_Name = "Configuration" 2 | Option Explicit 3 | 4 | Sub GetConfiguration() 5 | Dim clooConfiguration As New ClooWrapperVBA.Configuration 6 | Dim nPlatforms As Long 7 | Dim nDevices As Long 8 | Dim i%, j%, k%, currentColumn%, nColumns%, nRows% 9 | Dim tmpStrings() As String 10 | Dim result As Boolean 11 | Dim wsConfiguration As Worksheet 12 | 13 | Set wsConfiguration = ThisWorkbook.Worksheets("Configuration") 14 | 15 | ' Cleanup. 16 | nColumns = wsConfiguration.Cells(1, Columns.Count).End(xlToLeft).Column 17 | For i = 1 To nColumns 18 | nRows = wsConfiguration.Cells(Rows.Count, i).End(xlUp).Row 19 | wsConfiguration.Range(wsConfiguration.Cells(1, i), wsConfiguration.Cells(nRows, i)).ClearContents 20 | Next i 21 | 22 | nPlatforms = clooConfiguration.platforms 23 | 24 | For i = 1 To nPlatforms 25 | result = clooConfiguration.SetPlatform(i - 1) 26 | If result Then 27 | currentColumn = currentColumn + 1 28 | wsConfiguration.Cells(1, currentColumn) = "Platform" 29 | wsConfiguration.Cells(2, currentColumn) = "Name" 30 | wsConfiguration.Cells(3, currentColumn) = "Vendor" 31 | wsConfiguration.Cells(4, currentColumn) = "Profile" 32 | wsConfiguration.Cells(5, currentColumn) = "Version" 33 | wsConfiguration.Cells(6, currentColumn) = "Extensions" 34 | currentColumn = currentColumn + 1 35 | wsConfiguration.Cells(1, currentColumn) = i - 1 36 | wsConfiguration.Cells(2, currentColumn) = clooConfiguration.Platform.platformName 37 | wsConfiguration.Cells(3, currentColumn) = clooConfiguration.Platform.platformVendor 38 | wsConfiguration.Cells(4, currentColumn) = clooConfiguration.Platform.PlatformProfile 39 | wsConfiguration.Cells(5, currentColumn) = clooConfiguration.Platform.platformVersion 40 | tmpStrings = clooConfiguration.Platform.PlatformExtensions 41 | For j = 0 To UBound(tmpStrings) 42 | wsConfiguration.Cells(6 + j, currentColumn) = tmpStrings(j) 43 | Next j 44 | 45 | nDevices = clooConfiguration.Platform.Devices 46 | For j = 1 To nDevices 47 | result = clooConfiguration.Platform.SetDevice(j - 1) 48 | If result Then 49 | currentColumn = currentColumn + 1 50 | wsConfiguration.Cells(1, currentColumn) = "Platform" 51 | wsConfiguration.Cells(2, currentColumn) = "Device" 52 | wsConfiguration.Cells(3, currentColumn) = "Type" 53 | wsConfiguration.Cells(4, currentColumn) = "Name" 54 | wsConfiguration.Cells(5, currentColumn) = "Vendor" 55 | wsConfiguration.Cells(6, currentColumn) = "MaxComputeUnits" 56 | wsConfiguration.Cells(7, currentColumn) = "AddressBits" 57 | wsConfiguration.Cells(8, currentColumn) = "DeviceAvailable" 58 | wsConfiguration.Cells(9, currentColumn) = "CompilerAvailable" 59 | wsConfiguration.Cells(10, currentColumn) = "CommandQueueFlags" 60 | wsConfiguration.Cells(11, currentColumn) = "DeviceVersion" 61 | wsConfiguration.Cells(12, currentColumn) = "DriverVersion" 62 | wsConfiguration.Cells(13, currentColumn) = "EndianLittle" 63 | wsConfiguration.Cells(14, currentColumn) = "ErrorCorrectionSupport" 64 | wsConfiguration.Cells(15, currentColumn) = "SingleCapabilites" 65 | wsConfiguration.Cells(16, currentColumn) = "ExecutionCapabilities" 66 | wsConfiguration.Cells(17, currentColumn) = "DeviceExtensions" 67 | wsConfiguration.Cells(18, currentColumn) = "GlobalMemoryCacheLineSize, bytes" 68 | wsConfiguration.Cells(19, currentColumn) = "GlobalMemoryCacheSize, bytes" 69 | wsConfiguration.Cells(20, currentColumn) = "GlobalMemoryCacheType" 70 | wsConfiguration.Cells(21, currentColumn) = "GlobalMemorySize, bytes" 71 | wsConfiguration.Cells(22, currentColumn) = "HostUnifiedMemory" 72 | wsConfiguration.Cells(23, currentColumn) = "ImageSupport" 73 | wsConfiguration.Cells(24, currentColumn) = "Image2DMaxHeight" 74 | wsConfiguration.Cells(25, currentColumn) = "Image2DMaxWidth" 75 | wsConfiguration.Cells(26, currentColumn) = "Image3DMaxDepth" 76 | wsConfiguration.Cells(27, currentColumn) = "Image3DMaxHeight" 77 | wsConfiguration.Cells(28, currentColumn) = "Image3DMaxWidth" 78 | wsConfiguration.Cells(29, currentColumn) = "LocalMemorySize, bytes" 79 | wsConfiguration.Cells(30, currentColumn) = "LocalMemoryType" 80 | wsConfiguration.Cells(31, currentColumn) = "MaxClockFrequency, MHz" 81 | wsConfiguration.Cells(32, currentColumn) = "MaxConstantArguments" 82 | wsConfiguration.Cells(33, currentColumn) = "MaxConstantBufferSize, bytes" 83 | wsConfiguration.Cells(34, currentColumn) = "MaxMemoryAllocationSize, bytes" 84 | wsConfiguration.Cells(35, currentColumn) = "MaxParameterSize, bytes" 85 | wsConfiguration.Cells(36, currentColumn) = "MaxReadImageArguments" 86 | wsConfiguration.Cells(37, currentColumn) = "MaxSamplers" 87 | wsConfiguration.Cells(38, currentColumn) = "MaxWorkGroupSize" 88 | wsConfiguration.Cells(39, currentColumn) = "MaxWorkItemDimensions" 89 | 90 | ' For k = 0 To UBound(cloo.Platform.device.MaxWorkItemSizes) 91 | ' wsConfiguration.Cells(40 + k, currentColumn) = "MaxWorkItem[" & CStr(k) & "] Size" 92 | ' Next k 93 | 94 | wsConfiguration.Cells(41 + k, currentColumn) = "MaxWriteImageArguments" 95 | wsConfiguration.Cells(42 + k, currentColumn) = "MemoryBaseAddressAlignment, bits" 96 | wsConfiguration.Cells(43 + k, currentColumn) = "MinDataTypeAlignmentSize, bytes" 97 | wsConfiguration.Cells(44 + k, currentColumn) = "NativeVectorWidthChar" 98 | wsConfiguration.Cells(45 + k, currentColumn) = "NativeVectorWidthDouble" 99 | wsConfiguration.Cells(46 + k, currentColumn) = "NativeVectorWidthFloat" 100 | wsConfiguration.Cells(47 + k, currentColumn) = "NativeVectorWidthHalf" 101 | wsConfiguration.Cells(48 + k, currentColumn) = "NativeVectorWidthInt" 102 | wsConfiguration.Cells(49 + k, currentColumn) = "NativeVectorWidthLong" 103 | wsConfiguration.Cells(50 + k, currentColumn) = "NativeVectorWidthShort" 104 | wsConfiguration.Cells(51 + k, currentColumn) = "OpenCLCVersionString" 105 | wsConfiguration.Cells(52 + k, currentColumn) = "PreferredVectorWidthChar" 106 | wsConfiguration.Cells(53 + k, currentColumn) = "PreferredVectorWidthDouble" 107 | wsConfiguration.Cells(54 + k, currentColumn) = "PreferredVectorWidthFloat" 108 | wsConfiguration.Cells(55 + k, currentColumn) = "PreferredVectorWidthHalf" 109 | wsConfiguration.Cells(56 + k, currentColumn) = "PreferredVectorWidthInt" 110 | wsConfiguration.Cells(57 + k, currentColumn) = "PreferredVectorWidthLong" 111 | wsConfiguration.Cells(58 + k, currentColumn) = "PreferredVectorWidthShort" 112 | wsConfiguration.Cells(59 + k, currentColumn) = "Profile" 113 | wsConfiguration.Cells(60 + k, currentColumn) = "ProfilingTimerResolution, ns" 114 | wsConfiguration.Cells(61 + k, currentColumn) = "VendorId" 115 | currentColumn = currentColumn + 1 116 | wsConfiguration.Cells(1, currentColumn) = i - 1 117 | wsConfiguration.Cells(2, currentColumn) = j - 1 118 | wsConfiguration.Cells(3, currentColumn) = clooConfiguration.Platform.device.deviceType 119 | wsConfiguration.Cells(4, currentColumn) = clooConfiguration.Platform.device.deviceName 120 | wsConfiguration.Cells(5, currentColumn) = clooConfiguration.Platform.device.deviceVendor 121 | wsConfiguration.Cells(6, currentColumn) = clooConfiguration.Platform.device.maxComputeUnits 122 | wsConfiguration.Cells(7, currentColumn) = clooConfiguration.Platform.device.AddressBits 123 | wsConfiguration.Cells(8, currentColumn) = clooConfiguration.Platform.device.deviceAvailable 124 | wsConfiguration.Cells(9, currentColumn) = clooConfiguration.Platform.device.compilerAvailable 125 | wsConfiguration.Cells(10, currentColumn) = clooConfiguration.Platform.device.CommandQueueFlags 126 | wsConfiguration.Cells(11, currentColumn) = clooConfiguration.Platform.device.deviceVersion 127 | wsConfiguration.Cells(12, currentColumn) = clooConfiguration.Platform.device.driverVersion 128 | wsConfiguration.Cells(13, currentColumn) = clooConfiguration.Platform.device.EndianLittle 129 | wsConfiguration.Cells(14, currentColumn) = clooConfiguration.Platform.device.ErrorCorrectionSupport 130 | wsConfiguration.Cells(15, currentColumn) = clooConfiguration.Platform.device.SingleCapabilites 131 | wsConfiguration.Cells(16, currentColumn) = clooConfiguration.Platform.device.ExecutionCapabilities 132 | wsConfiguration.Cells(17, currentColumn) = clooConfiguration.Platform.device.DeviceExtensions 133 | wsConfiguration.Cells(18, currentColumn) = clooConfiguration.Platform.device.GlobalMemoryCacheLineSize 134 | wsConfiguration.Cells(19, currentColumn) = clooConfiguration.Platform.device.GlobalMemoryCacheSize 135 | wsConfiguration.Cells(20, currentColumn) = clooConfiguration.Platform.device.GlobalMemoryCacheType 136 | wsConfiguration.Cells(21, currentColumn) = clooConfiguration.Platform.device.globalMemorySize 137 | wsConfiguration.Cells(22, currentColumn) = clooConfiguration.Platform.device.HostUnifiedMemory 138 | wsConfiguration.Cells(23, currentColumn) = clooConfiguration.Platform.device.ImageSupport 139 | wsConfiguration.Cells(24, currentColumn) = clooConfiguration.Platform.device.Image2DMaxHeight 140 | wsConfiguration.Cells(25, currentColumn) = clooConfiguration.Platform.device.Image2DMaxWidth 141 | wsConfiguration.Cells(26, currentColumn) = clooConfiguration.Platform.device.Image3DMaxDepth 142 | wsConfiguration.Cells(27, currentColumn) = clooConfiguration.Platform.device.Image3DMaxHeight 143 | wsConfiguration.Cells(28, currentColumn) = clooConfiguration.Platform.device.Image3DMaxWidth 144 | wsConfiguration.Cells(29, currentColumn) = clooConfiguration.Platform.device.LocalMemorySize 145 | wsConfiguration.Cells(30, currentColumn) = clooConfiguration.Platform.device.LocalMemoryType 146 | wsConfiguration.Cells(31, currentColumn) = clooConfiguration.Platform.device.maxClockFrequency 147 | wsConfiguration.Cells(32, currentColumn) = clooConfiguration.Platform.device.MaxConstantArguments 148 | wsConfiguration.Cells(33, currentColumn) = clooConfiguration.Platform.device.MaxConstantBufferSize 149 | wsConfiguration.Cells(34, currentColumn) = clooConfiguration.Platform.device.maxMemoryAllocationSize 150 | wsConfiguration.Cells(35, currentColumn) = clooConfiguration.Platform.device.MaxParameterSize 151 | wsConfiguration.Cells(36, currentColumn) = clooConfiguration.Platform.device.MaxReadImageArguments 152 | wsConfiguration.Cells(37, currentColumn) = clooConfiguration.Platform.device.MaxSamplers 153 | wsConfiguration.Cells(38, currentColumn) = clooConfiguration.Platform.device.MaxWorkGroupSize 154 | wsConfiguration.Cells(39, currentColumn) = clooConfiguration.Platform.device.MaxWorkItemDimensions 155 | 156 | ' For k = 0 To UBound(cloo.Platform.device.MaxWorkItemSizes) 157 | ' wsConfiguration.Cells(40 + k, currentColumn) = cloo.Platform.device.MaxWorkItemSizes(k) 158 | ' Next k 159 | 160 | wsConfiguration.Cells(41 + k, currentColumn) = clooConfiguration.Platform.device.MaxWriteImageArguments 161 | wsConfiguration.Cells(42 + k, currentColumn) = clooConfiguration.Platform.device.MemoryBaseAddressAlignment 162 | wsConfiguration.Cells(43 + k, currentColumn) = clooConfiguration.Platform.device.MinDataTypeAlignmentSize 163 | wsConfiguration.Cells(44 + k, currentColumn) = clooConfiguration.Platform.device.NativeVectorWidthChar 164 | wsConfiguration.Cells(45 + k, currentColumn) = clooConfiguration.Platform.device.NativeVectorWidthDouble 165 | wsConfiguration.Cells(46 + k, currentColumn) = clooConfiguration.Platform.device.NativeVectorWidthFloat 166 | wsConfiguration.Cells(47 + k, currentColumn) = clooConfiguration.Platform.device.NativeVectorWidthHalf 167 | wsConfiguration.Cells(48 + k + k, currentColumn) = clooConfiguration.Platform.device.NativeVectorWidthInt 168 | wsConfiguration.Cells(49, currentColumn) = clooConfiguration.Platform.device.NativeVectorWidthLong 169 | wsConfiguration.Cells(50 + k, currentColumn) = clooConfiguration.Platform.device.NativeVectorWidthShort 170 | wsConfiguration.Cells(51 + k, currentColumn) = clooConfiguration.Platform.device.openCLCVersionString 171 | wsConfiguration.Cells(52 + k, currentColumn) = clooConfiguration.Platform.device.PreferredVectorWidthChar 172 | wsConfiguration.Cells(53 + k, currentColumn) = clooConfiguration.Platform.device.PreferredVectorWidthDouble 173 | wsConfiguration.Cells(54 + k, currentColumn) = clooConfiguration.Platform.device.PreferredVectorWidthFloat 174 | wsConfiguration.Cells(55 + k, currentColumn) = clooConfiguration.Platform.device.PreferredVectorWidthHalf 175 | wsConfiguration.Cells(56 + k, currentColumn) = clooConfiguration.Platform.device.PreferredVectorWidthInt 176 | wsConfiguration.Cells(57 + k, currentColumn) = clooConfiguration.Platform.device.PreferredVectorWidthLong 177 | wsConfiguration.Cells(58 + k, currentColumn) = clooConfiguration.Platform.device.PreferredVectorWidthShort 178 | wsConfiguration.Cells(59 + k, currentColumn) = clooConfiguration.Platform.device.Profile 179 | wsConfiguration.Cells(60 + k, currentColumn) = clooConfiguration.Platform.device.ProfilingTimerResolution 180 | wsConfiguration.Cells(61 + k, currentColumn) = clooConfiguration.Platform.device.VendorId 181 | End If 182 | Next j 183 | End If 184 | Next i 185 | End Sub 186 | -------------------------------------------------------------------------------- /Excel/Performance.bas: -------------------------------------------------------------------------------- 1 | Attribute VB_Name = "Performance" 2 | Option Explicit 3 | 4 | Private Const ARRAY_SIZE = 1000 5 | 6 | Sub VBA_PerformanceTest() 7 | Dim wsPerformanceTest As Worksheet 8 | Dim m1!(), m2!(), vecM1!(), vecM2!(), vecResp!(), resultVba!(), vecQ&(0) 9 | Dim x1!(0), x2!(0), res!(0) 10 | Dim finalResults!() 11 | Dim i&, j&, k&, p&, q&, r& 12 | Dim buildLogs$, sources$, result As Boolean 13 | Dim cTime As New CTimer 14 | Dim globalWorkSize&(1), localWorkSize&(), globalWorkOffset&() 15 | Dim calcCorrect As Boolean 16 | Dim programDevice_Performance As ClooWrapperVBA.ProgramDevice 17 | Dim progDevices As Collection 18 | 19 | Set wsPerformanceTest = ThisWorkbook.Worksheets("Performance") 20 | wsPerformanceTest.Range("B2:C4").ClearContents 21 | 22 | p = ARRAY_SIZE: q = ARRAY_SIZE: r = ARRAY_SIZE 23 | 24 | ReDim resultVba(p - 1, r - 1) 25 | 26 | ' Dimensions of matrices: 27 | ReDim m1(p - 1, q - 1) 28 | ReDim m2(q - 1, r - 1) 29 | ReDim vecResp(p * r - 1) 30 | 31 | Randomize 32 | For i = 0 To p - 1 33 | For j = 0 To q - 1 34 | m1(i, j) = CInt((Rnd() - 0.5) * 100#) 35 | Next j 36 | Next i 37 | 38 | For i = 0 To q - 1 39 | For j = 0 To r - 1 40 | m2(i, j) = CInt((Rnd() - 0.5) * 100#) 41 | Next j 42 | Next i 43 | vecM1 = MatrixToVectorSingle(m1, p, q) 44 | vecM2 = MatrixToVectorSingle(m2, q, r) 45 | 46 | ' VBA matrix multiplication: 47 | cTime.StartCounter 48 | For i = 0 To p - 1 49 | For j = 0 To r - 1 50 | For k = 0 To q - 1 51 | resultVba(i, j) = resultVba(i, j) + m1(i, k) * m2(k, j) 52 | Next k 53 | Next j 54 | Next i 55 | wsPerformanceTest.Cells(2, 2) = cTime.TimeElapsed 56 | 57 | Open Application.ActiveWorkbook.Path & "\cl\FloatMatrixMultiplication.cl" For Binary As #1 58 | sources = Space$(LOF(1)) 59 | Get #1, , sources 60 | Close #1 61 | 62 | ' Adding of all CPU and GPU devices to collection. 63 | Set progDevices = CreateDeviceCollection(sources) 64 | 65 | If progDevices Is Nothing Then 66 | MsgBox ("No devices found! Something is wrong!") 67 | Exit Sub 68 | End If 69 | 70 | If Not (GetFirstDeviceOfType(progDevices, "CPU") Is Nothing) Then 71 | ' CPU calculations. 72 | Set programDevice_Performance = GetFirstDeviceOfType(progDevices, "CPU") 73 | 74 | result = programDevice_Performance.CreateKernel("FloatMatrixMult") 75 | 76 | globalWorkSize(0) = p 77 | globalWorkSize(1) = r 78 | vecQ(0) = q 79 | 80 | result = programDevice_Performance.SetMemoryArgument_Single(0, vecResp) 81 | result = programDevice_Performance.SetMemoryArgument_Single(1, vecM1) 82 | result = programDevice_Performance.SetMemoryArgument_Single(2, vecM2) 83 | result = programDevice_Performance.SetMemoryArgument_Long(3, vecQ) 84 | 85 | ' Start once to update cashes. 86 | result = programDevice_Performance.ExecuteSync(globalWorkOffset, globalWorkSize, localWorkSize) 87 | 88 | ' Start real measurements. 89 | cTime.StartCounter 90 | result = programDevice_Performance.ExecuteSync(globalWorkOffset, globalWorkSize, localWorkSize) 91 | wsPerformanceTest.Cells(3, 2) = cTime.TimeElapsed 92 | 93 | result = programDevice_Performance.GetMemoryArgument_Single(0, vecResp) 94 | finalResults = VectorToMatrixSingle(vecResp, p, r) 95 | 96 | ' Comparison to VBA result. 97 | calcCorrect = True 98 | For i = 0 To p - 1 99 | For j = 0 To r - 1 100 | If Abs(finalResults(i, j) - resultVba(i, j)) > 1E-20 Then 101 | calcCorrect = False 102 | End If 103 | Next j 104 | Next i 105 | wsPerformanceTest.Cells(3, 3) = calcCorrect 106 | 107 | result = programDevice_Performance.ReleaseMemObject(3) 108 | result = programDevice_Performance.ReleaseMemObject(2) 109 | result = programDevice_Performance.ReleaseMemObject(1) 110 | result = programDevice_Performance.ReleaseMemObject(0) 111 | result = programDevice_Performance.ReleaseKernel 112 | result = programDevice_Performance.ReleaseProgram 113 | Else 114 | wsPerformanceTest.Cells(3, 2) = CVErr(2042) 115 | wsPerformanceTest.Cells(3, 3) = CVErr(2042) 116 | End If 117 | 118 | ' GPU calculations. 119 | If Not (GetFirstDeviceOfType(progDevices, "GPU") Is Nothing) Then 120 | Set programDevice_Performance = GetFirstDeviceOfType(progDevices, "GPU") 121 | 122 | result = programDevice_Performance.CreateKernel("FloatMatrixMult") 123 | 124 | globalWorkSize(0) = p 125 | globalWorkSize(1) = r 126 | vecQ(0) = q 127 | 128 | ReDim vecResp(p * r - 1) 129 | result = programDevice_Performance.SetMemoryArgument_Single(0, vecResp) 130 | result = programDevice_Performance.SetMemoryArgument_Single(1, vecM1) 131 | result = programDevice_Performance.SetMemoryArgument_Single(2, vecM2) 132 | result = programDevice_Performance.SetMemoryArgument_Long(3, vecQ) 133 | 134 | ' Start once to update cashes. 135 | Call programDevice_Performance.ExecuteSync(globalWorkOffset, globalWorkSize, localWorkSize) 136 | 137 | ' Start real measurements. 138 | cTime.StartCounter 139 | result = programDevice_Performance.ExecuteSync(globalWorkOffset, globalWorkSize, localWorkSize) 140 | wsPerformanceTest.Cells(4, 2) = cTime.TimeElapsed 141 | 142 | result = programDevice_Performance.GetMemoryArgument_Single(0, vecResp) 143 | finalResults = VectorToMatrixSingle(vecResp, p, r) 144 | 145 | ' Comparison to VBA result. 146 | calcCorrect = True 147 | For i = 0 To p - 1 148 | For j = 0 To r - 1 149 | If Abs(finalResults(i, j) - resultVba(i, j)) > 1E-20 Then 150 | calcCorrect = False 151 | End If 152 | Next j 153 | Next i 154 | wsPerformanceTest.Cells(4, 3) = calcCorrect 155 | result = programDevice_Performance.ReleaseMemObject(3) 156 | result = programDevice_Performance.ReleaseMemObject(2) 157 | result = programDevice_Performance.ReleaseMemObject(1) 158 | result = programDevice_Performance.ReleaseMemObject(0) 159 | result = programDevice_Performance.ReleaseKernel 160 | result = programDevice_Performance.ReleaseProgram 161 | Else 162 | wsPerformanceTest.Cells(4, 2) = CVErr(2042) 163 | wsPerformanceTest.Cells(4, 3) = CVErr(2042) 164 | End If 165 | End Sub 166 | 167 | Sub GpuCpu_FloatDouble_PerformanceTest() 168 | GpuCpu_Float_PerformanceTest 169 | GpuCpu_Double_PerformanceTest 170 | End Sub 171 | 172 | Sub GpuCpu_Float_PerformanceTest() 173 | Dim wsPerformanceTest As Worksheet 174 | Dim upper&, singles!(), aSingle!, i& 175 | Dim sources$, result As Boolean 176 | Dim progDevices As Collection 177 | Dim programDevice_Performance As ClooWrapperVBA.ProgramDevice 178 | 179 | Set wsPerformanceTest = ThisWorkbook.Worksheets("Performance") 180 | wsPerformanceTest.Range("E3:E4").ClearContents 181 | 182 | upper = 10000000 183 | ReDim singles(upper) 184 | 185 | For i = 0 To upper - 1 186 | singles(i) = i 187 | Next i 188 | aSingle = 2! 189 | 190 | Open Application.ActiveWorkbook.Path & "\cl\FloatPerformance.cl" For Binary As #1 191 | sources = Space$(LOF(1)) 192 | Get #1, , sources 193 | Close #1 194 | 195 | ' Adding of all CPU and GPU devices to collection. 196 | Set progDevices = CreateDeviceCollection(sources) 197 | 198 | If progDevices Is Nothing Then 199 | MsgBox ("No devices found! Something is wrong!") 200 | Exit Sub 201 | End If 202 | 203 | If GetFirstDeviceOfType(progDevices, "GPU") Is Nothing Then 204 | wsPerformanceTest.Cells(4, 5) = CVErr(2042) 205 | Else 206 | Set programDevice_Performance = GetFirstDeviceOfType(progDevices, "GPU") 207 | wsPerformanceTest.Cells(4, 5) = PerformanceTest_Single(upper, singles, aSingle, programDevice_Performance) 208 | 209 | result = programDevice_Performance.ReleaseMemObject(1) 210 | result = programDevice_Performance.ReleaseMemObject(0) 211 | result = programDevice_Performance.ReleaseKernel 212 | result = programDevice_Performance.ReleaseProgram 213 | End If 214 | 215 | If GetFirstDeviceOfType(progDevices, "CPU") Is Nothing Then 216 | wsPerformanceTest.Cells(3, 5) = CVErr(2042) 217 | Else 218 | Set programDevice_Performance = GetFirstDeviceOfType(progDevices, "CPU") 219 | wsPerformanceTest.Cells(3, 5) = PerformanceTest_Single(upper, singles, aSingle, programDevice_Performance) 220 | 221 | result = programDevice_Performance.ReleaseMemObject(1) 222 | result = programDevice_Performance.ReleaseMemObject(0) 223 | result = programDevice_Performance.ReleaseKernel 224 | result = programDevice_Performance.ReleaseProgram 225 | End If 226 | End Sub 227 | 228 | Sub GpuCpu_Double_PerformanceTest() 229 | Dim wsPerformanceTest As Worksheet 230 | Dim upper&, doubles#(), aDouble#, i& 231 | Dim sources$, result As Boolean 232 | Dim progDevices As Collection 233 | Dim programDevice_Performance As ClooWrapperVBA.ProgramDevice 234 | 235 | Set wsPerformanceTest = ThisWorkbook.Worksheets("Performance") 236 | wsPerformanceTest.Range("F3:F4").ClearContents 237 | 238 | upper = 10000000 239 | ReDim doubles(upper) 240 | 241 | For i = 0 To upper - 1 242 | doubles(i) = i 243 | Next i 244 | aDouble = 2# 245 | 246 | Open Application.ActiveWorkbook.Path & "\cl\DoublePerformance.cl" For Binary As #1 247 | sources = Space$(LOF(1)) 248 | Get #1, , sources 249 | Close #1 250 | 251 | ' Adding of all CPU and GPU devices to collection. 252 | Set progDevices = CreateDeviceCollection(sources) 253 | 254 | If progDevices Is Nothing Then 255 | MsgBox ("No devices found! Something is wrong!") 256 | Exit Sub 257 | End If 258 | 259 | If GetFirstDeviceOfType(progDevices, "GPU") Is Nothing Then 260 | wsPerformanceTest.Cells(4, 6) = CVErr(2042) 261 | Else 262 | Set programDevice_Performance = GetFirstDeviceOfType(progDevices, "GPU") 263 | wsPerformanceTest.Cells(4, 6) = PerformanceTest_Double(upper, doubles, aDouble, programDevice_Performance) 264 | 265 | result = programDevice_Performance.ReleaseMemObject(1) 266 | result = programDevice_Performance.ReleaseMemObject(0) 267 | result = programDevice_Performance.ReleaseKernel 268 | result = programDevice_Performance.ReleaseProgram 269 | End If 270 | 271 | If GetFirstDeviceOfType(progDevices, "CPU") Is Nothing Then 272 | wsPerformanceTest.Cells(3, 6) = CVErr(2042) 273 | Else 274 | Set programDevice_Performance = GetFirstDeviceOfType(progDevices, "CPU") 275 | wsPerformanceTest.Cells(3, 6) = PerformanceTest_Double(upper, doubles, aDouble, programDevice_Performance) 276 | 277 | result = programDevice_Performance.ReleaseMemObject(1) 278 | result = programDevice_Performance.ReleaseMemObject(0) 279 | result = programDevice_Performance.ReleaseKernel 280 | result = programDevice_Performance.ReleaseProgram 281 | End If 282 | End Sub 283 | 284 | ' Single precision performance at CPU / GPU. 285 | Function PerformanceTest_Single(upper&, singles!(), aSingle!, programDevice_Performance As ClooWrapperVBA.ProgramDevice) 286 | Dim buildLogs$, result As Boolean 287 | 288 | result = programDevice_Performance.CreateKernel("FloatPerformance") 289 | 290 | result = programDevice_Performance.SetMemoryArgument_Single(0, singles) 291 | result = programDevice_Performance.SetValueArgument_Single(1, aSingle) 292 | 293 | PerformanceTest_Single = PerformanceTestExecution(upper, programDevice_Performance) 294 | End Function 295 | 296 | ' Double precision performance at CPU / GPU. 297 | Function PerformanceTest_Double(upper&, doubles#(), aDouble#, programDevice_Performance As ClooWrapperVBA.ProgramDevice) 298 | Dim buildLogs$, result As Boolean 299 | 300 | result = programDevice_Performance.CreateKernel("DoublePerformance") 301 | 302 | result = programDevice_Performance.SetMemoryArgument_Double(0, doubles) 303 | result = programDevice_Performance.SetValueArgument_Double(1, aDouble) 304 | 305 | PerformanceTest_Double = PerformanceTestExecution(upper, programDevice_Performance) 306 | End Function 307 | 308 | Function PerformanceTestExecution(upper&, programDevice_Performance) 309 | Dim globalWorkSize&(0), localWorkSize&(), globalWorkOffset&() 310 | Dim elTime# 311 | Dim cTime As New CTimer 312 | 313 | cTime.StartCounter 314 | globalWorkSize(0) = 10 315 | Do While cTime.TimeElapsed < 25 316 | cTime.StartCounter 317 | 318 | Call programDevice_Performance.ExecuteSync(globalWorkOffset, globalWorkSize, localWorkSize) 319 | 320 | If globalWorkSize(0) = upper Then 321 | Exit Do 322 | End If 323 | 324 | globalWorkSize(0) = globalWorkSize(0) * 2 325 | 326 | If globalWorkSize(0) > upper Then 327 | elTime = cTime.TimeElapsed / 1000# 328 | globalWorkSize(0) = upper 329 | End If 330 | Loop 331 | 332 | elTime = cTime.TimeElapsed / 1000# 333 | 334 | PerformanceTestExecution = (4096# * globalWorkSize(0) / elTime / 1000000000#) 335 | End Function 336 | 337 | Sub Test_OneAfterAnother() 338 | Dim m1!(), m2!(), vecM1!(), vecM2!(), vecResp!(), resultVba!(), vecQ&(0) 339 | Dim x1!(0), x2!(0), res!(0) 340 | Dim finalResults!() 341 | Dim i&, j&, k&, p&, q&, r& 342 | Dim buildLogs$, sources$, result As Boolean 343 | Dim cTime As New CTimer 344 | Dim globalWorkSize&(1), localWorkSize&(), globalWorkOffset&() 345 | Dim calcCorrect As Boolean 346 | Dim programDevice_Performance As ClooWrapperVBA.ProgramDevice 347 | Dim progDevices As Collection 348 | 349 | p = 2: q = 2: r = 2 350 | 351 | ReDim resultVba(p - 1, r - 1) 352 | 353 | ' Dimensions of matrices: 354 | ReDim m1(p - 1, q - 1) 355 | ReDim m2(q - 1, r - 1) 356 | ReDim vecResp(p * r - 1) 357 | 358 | m1(0, 0) = 1: m1(0, 1) = 2: m1(1, 0) = 3: m1(1, 1) = 4 359 | m2(0, 0) = 2: m2(0, 1) = 3: m2(1, 0) = 4: m2(1, 1) = 5 360 | 361 | vecM1 = MatrixToVector(m1, p, q) 362 | vecM2 = MatrixToVector(m2, q, r) 363 | 364 | ' VBA matrix multiplication: 365 | For i = 0 To p - 1 366 | For j = 0 To r - 1 367 | For k = 0 To q - 1 368 | resultVba(i, j) = resultVba(i, j) + m1(i, k) * m2(k, j) 369 | Next k 370 | Next j 371 | Next i 372 | 373 | Open Application.ActiveWorkbook.Path & "\cl\FloatMatrixMultiplication.cl" For Binary As #1 374 | sources = Space$(LOF(1)) 375 | Get #1, , sources 376 | Close #1 377 | 378 | ' Adding of all CPU and GPU devices to collection. 379 | Set progDevices = CreateDeviceCollection(sources) 380 | 381 | If progDevices Is Nothing Then 382 | MsgBox ("No devices found! Something is wrong!") 383 | Exit Sub 384 | End If 385 | 386 | If Not (GetFirstDeviceOfType(progDevices, "CPU") Is Nothing) Then 387 | ' CPU calculations. 388 | Set programDevice_Performance = GetFirstDeviceOfType(progDevices, "CPU") 389 | 390 | result = programDevice_Performance.CreateKernel("FloatMatrixMult") 391 | 392 | globalWorkSize(0) = p 393 | globalWorkSize(1) = r 394 | vecQ(0) = q 395 | 396 | result = programDevice_Performance.SetMemoryArgument_Single(0, vecResp) 397 | result = programDevice_Performance.SetMemoryArgument_Single(1, vecM1) 398 | result = programDevice_Performance.SetMemoryArgument_Single(2, vecM2) 399 | result = programDevice_Performance.SetMemoryArgument_Long(3, vecQ) 400 | 401 | result = programDevice_Performance.ExecuteSync(globalWorkOffset, globalWorkSize, localWorkSize) 402 | 403 | result = programDevice_Performance.GetMemoryArgument_Single(0, vecResp) 404 | finalResults = VectorToMatrix(vecResp, p, r) 405 | 406 | ' Comparison to VBA result. 407 | calcCorrect = True 408 | For i = 0 To p - 1 409 | For j = 0 To r - 1 410 | If Abs(finalResults(i, j) - resultVba(i, j)) > 1E-20 Then 411 | calcCorrect = False 412 | End If 413 | Next j 414 | Next i 415 | 416 | result = programDevice_Performance.SetMemoryArgument_Single(1, vecM2) 417 | result = programDevice_Performance.SetMemoryArgument_Single(2, vecM1) 418 | 419 | result = programDevice_Performance.ExecuteSync(globalWorkOffset, globalWorkSize, localWorkSize) 420 | result = programDevice_Performance.GetMemoryArgument_Single(0, vecResp) 421 | finalResults = VectorToMatrix(vecResp, p, r) 422 | 423 | ' VBA matrix multiplication: 424 | ReDim resultVba(p - 1, r - 1) 425 | For i = 0 To p - 1 426 | For j = 0 To r - 1 427 | For k = 0 To q - 1 428 | resultVba(i, j) = resultVba(i, j) + m2(i, k) * m1(k, j) 429 | Next k 430 | Next j 431 | Next i 432 | 433 | ' Comparison to VBA result. 434 | calcCorrect = True 435 | For i = 0 To p - 1 436 | For j = 0 To r - 1 437 | If Abs(finalResults(i, j) - resultVba(i, j)) > 1E-20 Then 438 | calcCorrect = False 439 | End If 440 | Next j 441 | Next i 442 | End If 443 | End Sub 444 | -------------------------------------------------------------------------------- /C#/ClooWrapperVBA/ProgramDevice.cs: -------------------------------------------------------------------------------- 1 | using Cloo; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Runtime.InteropServices; 5 | using System.Threading; 6 | 7 | namespace ClooWrapperVBA 8 | { 9 | /// 10 | /// ProgramDevice interface. 11 | /// 12 | [ComVisible(true)] 13 | [Guid("2BF7DA6B-DDB3-42A5-BD65-92EE93ABB473")] 14 | [InterfaceType(ComInterfaceType.InterfaceIsIDispatch)] 15 | public interface IProgramDevice 16 | { 17 | /// 18 | /// Creates kernel for method. 19 | /// 20 | /// Method. 21 | /// False in case of error/exception. Otherwise true. 22 | [DispId(1)] 23 | bool CreateKernel(string method); 24 | 25 | /// 26 | /// Initializes device of selected and . 27 | /// Loads sources and compiles them. 28 | /// 29 | /// Sources as plain text. 30 | /// Compilation options. 31 | /// Platform index (). 32 | /// Device index (). 33 | /// Device index inside one device type that corresponds to device index (for example, more than 1 "GPU" can be 34 | /// installed on the current platform). 35 | /// Build logs as single string. 36 | /// True, if the sources were compiled successfully, false otherwise. 37 | [DispId(2)] 38 | bool Build(string sourceCode, string options, int platformIndex, int deviceIndex, int deviceTypeIndex, out string buildLogs); 39 | 40 | #region SetArguments 41 | 42 | /// 43 | /// Writes an array of type "Long" to the device. 44 | /// Be careful: The sequence of "SetMemoryArgument" must correspond to the sequence of argument in the method! 45 | /// 46 | /// The argument index. 47 | /// Array of "Long". 48 | /// True, if the operation was successful, false otherwise. 49 | [DispId(3)] 50 | bool SetMemoryArgument_Long(int argument_index, ref int[] values); 51 | 52 | /// 53 | /// Writes an array of type "Single" to the device. 54 | /// Be careful: The sequence of "SetMemoryArgument" must correspond to the sequence of argument in the method! 55 | /// 56 | /// The argument index. 57 | /// Array of "Single". 58 | /// True, if the operation was successful, false otherwise. 59 | [DispId(4)] 60 | bool SetMemoryArgument_Single(int argument_index, ref float[] values); 61 | 62 | /// 63 | /// Writes an array of type "Double" to the device. 64 | /// Be careful: The sequence of "SetMemoryArgument" must correspond to the sequence of argument in the method! 65 | /// 66 | /// The argument index. 67 | /// Array of "Double". 68 | /// True, if the operation was successful, false otherwise. 69 | [DispId(5)] 70 | bool SetMemoryArgument_Double(int argument_index, ref double[] values); 71 | 72 | /// 73 | /// Sets "Long" argument to the kernel. 74 | /// 75 | /// The argument index. 76 | /// Argument value as "Long". 77 | /// True, if the operation was successful, false otherwise. 78 | [DispId(6)] 79 | bool SetValueArgument_Long(int argument_index, int value_long); 80 | 81 | /// 82 | /// Sets "Single" argument to the kernel. 83 | /// 84 | /// The argument index. 85 | /// Argument value as "Single". 86 | /// True, if the operation was successful, false otherwise. 87 | [DispId(7)] 88 | bool SetValueArgument_Single(int argument_index, float value_single); 89 | 90 | /// 91 | /// Sets "Double" argument to the kernel. 92 | /// 93 | /// The argument index. 94 | /// Argument value as "Double". 95 | /// True, if the operation was successful, false otherwise. 96 | [DispId(8)] 97 | bool SetValueArgument_Double(int argument_index, double value_double); 98 | 99 | #endregion SetArguments 100 | 101 | #region Execution 102 | 103 | /// 104 | /// Synchronous execution. 105 | /// 106 | /// Array of global work offset, or "null". 107 | /// Array of global work size, or "null". 108 | /// Array of local work size, or "null". 109 | /// False in case of error/exception. Otherwise true. 110 | [DispId(9)] 111 | bool ExecuteSync(ref int[] globalWorkOffset, ref int[] globalWorkSize, ref int[] localWorkSize); 112 | 113 | /// 114 | /// Execution in background. 115 | /// 116 | /// Array of global work offset, or "null". 117 | /// Array of global work size, or "null". 118 | /// Array of local work size, or "null". 119 | /// Thread priority as integer (0 - "Lowest", 1 - "BelowNormal", 2 - "Normal", 3 - "AboveNormal", 4 - "Highest"). 120 | /// False in case of error/exception. Otherwise true. 121 | [DispId(10)] 122 | bool ExecuteBackground(ref int[] globalWorkOffset, ref int[] globalWorkSize, ref int[] localWorkSize, int threadPriority); 123 | 124 | /// 125 | /// For asynchronous call from VBA we need an address of callback function because VBA can use events only 126 | /// from form/classes. 127 | /// 128 | /// Array of global work offset, or "null". 129 | /// Array of global work size, or "null". 130 | /// Array of local work size, or "null". 131 | /// Thread priority as integer (0 - "Lowest", 1 - "BelowNormal", 2 - "Normal", 3 - "AboveNormal", 4 - "Highest"). 132 | /// Callback to the VBA function. 133 | /// False in case of error/exception. Otherwise true. 134 | [DispId(11)] 135 | bool ExecuteAsync(ref int[] globalWorkOffset, ref int[] globalWorkSize, ref int[] localWorkSize, int threadPriority, 136 | [MarshalAs(UnmanagedType.FunctionPtr)] ref Action callback); 137 | 138 | /// 139 | /// True, if execution is completed, false otherwise. 140 | /// 141 | [DispId(12)] 142 | bool ExecutionCompleted { get; set; } 143 | 144 | #endregion Execution 145 | 146 | #region GetArguments 147 | 148 | /// 149 | /// Reads an array of type "Long" from the device. 150 | /// 151 | /// 0-based number of argument in argument list. 152 | /// Array of "Long". 153 | /// False in case of error/exception. Otherwise true. 154 | [DispId(13)] 155 | bool GetMemoryArgument_Long(int varIndex, ref int[] values); 156 | 157 | /// 158 | /// Reads an array of type "Single" from the device. 159 | /// 160 | /// 0-based number of argument in argument list. 161 | /// Array of "Single". 162 | /// False in case of error/exception. Otherwise true. 163 | [DispId(14)] 164 | bool GetMemoryArgument_Single(int varIndex, ref float[] values); 165 | 166 | /// 167 | /// Reads an array of type "Double" from the device. 168 | /// 169 | /// 0-based number of argument in argument list. 170 | /// Array of "Double". 171 | /// False in case of error/exception. Otherwise true. 172 | [DispId(15)] 173 | bool GetMemoryArgument_Double(int varIndex, ref double[] values); 174 | 175 | #endregion GetArguments 176 | 177 | #region Destructors 178 | 179 | /// 180 | /// Disposes kernel memory variable. 181 | /// 182 | /// 0-based index of argument in argument list. 183 | /// True, if the operation was successful, false otherwise. 184 | [DispId(16)] 185 | bool ReleaseMemObject(int argument_index); 186 | 187 | /// 188 | /// Disposes kernel. 189 | /// 190 | /// True, if the operation was successful, false otherwise. 191 | [DispId(17)] 192 | bool ReleaseKernel(); 193 | 194 | /// 195 | /// Disposes ComputeProgram, ComputeCommandQueue and CommandQueue. 196 | /// 197 | /// True, if the operation was successful, false otherwise. 198 | [DispId(18)] 199 | bool ReleaseProgram(); 200 | 201 | #endregion Destructors 202 | 203 | /// 204 | /// Device type of used device ("GPU" / "CPU"). 205 | /// 206 | [DispId(19)] 207 | string DeviceType { get; set; } 208 | 209 | /// 210 | /// Error string. 211 | /// 212 | [DispId(20)] 213 | string ErrorString { get; set; } 214 | } 215 | 216 | [ComVisible(true)] 217 | [Guid("56C41646-10CB-4188-979D-23F70E0FFDF5")] 218 | [ClassInterface(ClassInterfaceType.None)] 219 | public class ProgramDevice : IProgramDevice 220 | { 221 | public ComputeProgram ComputeProgram; 222 | public ComputeContext ComputeContext; 223 | public ComputeCommandQueue ComputeCommandQueue = null; 224 | private ComputeKernel kernel; 225 | private Dictionary variablePointers; 226 | private Action callBack; 227 | private long[] _globalWorkOffset = null; 228 | private long[] _globalWorkSize = null; 229 | private long[] _localWorkSize = null; 230 | 231 | /// 232 | /// Creates kernel for method. 233 | /// 234 | /// Method. 235 | /// False in case of error/exception. Otherwise true. 236 | public bool CreateKernel(string method) 237 | { 238 | try 239 | { 240 | kernel = ComputeProgram.CreateKernel(method); 241 | variablePointers = new Dictionary(); 242 | return true; 243 | } 244 | catch (Exception ex) 245 | { 246 | ErrorString += "\r\nError in CreateKernel: " + ex.Message; 247 | ErrorString += "\r\n" + ex.StackTrace; 248 | return false; 249 | } 250 | } 251 | 252 | /// 253 | /// Initializes device of selected and . 254 | /// Loads sources and compiles them. 255 | /// 256 | /// Sources as plain text. 257 | /// Compilation options. 258 | /// Platform index (). 259 | /// Device index (). 260 | /// Device index inside one device type that corresponds to device index (for example, more than 1 "GPU" can be 261 | /// installed on the current platform). 262 | /// Build logs as single string. 263 | /// True, if the sources were compiled successfully, false otherwise. 264 | public bool Build(string sourceCode, string options, int platformIndex, int deviceIndex, int deviceTypeIndex, out string buildLogs) 265 | { 266 | buildLogs = ""; 267 | 268 | Device device = new Device(platformIndex, deviceIndex); 269 | DeviceType = device.DeviceType; 270 | 271 | if (!device.CompilerAvailable) 272 | { 273 | buildLogs = "Compiler is not available for selected device."; 274 | return false; 275 | } 276 | 277 | try 278 | { 279 | ComputeContext = new ComputeContext(ComputePlatform.Platforms[platformIndex].Devices[deviceIndex].Type, 280 | new ComputeContextPropertyList(ComputePlatform.Platforms[platformIndex]), null, IntPtr.Zero); 281 | } 282 | catch (Exception e) 283 | { 284 | buildLogs = "Error during creation of ComputeContext:\r\n"; 285 | buildLogs += e.Message; 286 | return false; 287 | } 288 | 289 | try 290 | { 291 | ComputeCommandQueue = new ComputeCommandQueue(ComputeContext, ComputeContext.Devices[deviceTypeIndex], ComputeCommandQueueFlags.None); 292 | } 293 | catch (Exception e) 294 | { 295 | buildLogs = "Error during creation of ComputeCommandQueue:\r\n"; 296 | buildLogs += e.Message; 297 | return false; 298 | } 299 | 300 | ComputeProgram = new ComputeProgram(ComputeContext, sourceCode); 301 | 302 | try 303 | { 304 | ComputeProgram.Build(null, options, null, IntPtr.Zero); 305 | } 306 | catch (Exception e) 307 | { 308 | buildLogs = "Build failed.\r\n"; 309 | buildLogs += e.Message; 310 | return false; 311 | } 312 | 313 | buildLogs = ComputeProgram.GetBuildLog(ComputeContext.Devices[deviceTypeIndex]); 314 | 315 | return true; 316 | } 317 | 318 | #region SetArguments 319 | 320 | /// 321 | /// Writes an array of type "Long" to the device. 322 | /// 323 | /// 0-based index of argument in argument list. 324 | /// Array of "Long". 325 | /// True, if the operation was successful, false otherwise. 326 | public bool SetMemoryArgument_Long(int argument_index, ref int[] values) 327 | { 328 | try 329 | { 330 | ComputeMemory varPointer = new ComputeBuffer(ComputeContext, ComputeMemoryFlags.ReadWrite | ComputeMemoryFlags.CopyHostPointer, values); 331 | 332 | variablePointers[argument_index] = varPointer; 333 | kernel.SetMemoryArgument(argument_index, varPointer); 334 | 335 | return true; 336 | } 337 | catch (Exception ex) 338 | { 339 | ErrorString += "\r\nError in SetMemoryArgument_Long: " + ex.Message; 340 | ErrorString += "\r\n" + ex.StackTrace; 341 | return false; 342 | } 343 | } 344 | 345 | /// 346 | /// Writes an array of type "Single" to the device. 347 | /// 348 | /// 0-based index of argument in argument list. 349 | /// Array of "Single". 350 | /// True, if the operation was successful, false otherwise. 351 | public bool SetMemoryArgument_Single(int argument_index, ref float[] values) 352 | { 353 | try 354 | { 355 | ComputeMemory varPointer = new ComputeBuffer(ComputeContext, ComputeMemoryFlags.ReadWrite | ComputeMemoryFlags.CopyHostPointer, values); 356 | 357 | variablePointers[argument_index] = varPointer; 358 | kernel.SetMemoryArgument(argument_index, varPointer); 359 | 360 | return true; 361 | } 362 | catch (Exception ex) 363 | { 364 | ErrorString += "\r\nError in SetMemoryArgument_Single: " + ex.Message; 365 | ErrorString += "\r\n" + ex.StackTrace; 366 | return false; 367 | } 368 | } 369 | 370 | /// 371 | /// Writes an array of type "Double" to the device. 372 | /// 373 | /// 0-based index of argument in argument list. 374 | /// Array of "Double". 375 | /// True, if the operation was successful, false otherwise. 376 | public bool SetMemoryArgument_Double(int argument_index, ref double[] values) 377 | { 378 | try 379 | { 380 | ComputeMemory varPointer = new ComputeBuffer(ComputeContext, ComputeMemoryFlags.ReadWrite | ComputeMemoryFlags.CopyHostPointer, values); 381 | 382 | variablePointers[argument_index] = varPointer; 383 | kernel.SetMemoryArgument(argument_index, varPointer); 384 | 385 | return true; 386 | } 387 | catch (Exception ex) 388 | { 389 | ErrorString += "\r\nError in SetMemoryArgument_Double: " + ex.Message; 390 | ErrorString += "\r\n" + ex.StackTrace; 391 | return false; 392 | } 393 | } 394 | 395 | /// 396 | /// Sets "Long" argument to the kernel. 397 | /// 398 | /// 0-based index of argument in argument list. 399 | /// Argument value as "Long". 400 | /// True, if the operation was successful, false otherwise. 401 | public bool SetValueArgument_Long(int argument_index, int value_long) 402 | { 403 | try 404 | { 405 | ComputeMemory varPointer = new ComputeBuffer(ComputeContext, ComputeMemoryFlags.ReadWrite, 1); 406 | 407 | variablePointers[argument_index] = varPointer; 408 | kernel.SetValueArgument(argument_index, value_long); 409 | 410 | return true; 411 | } 412 | catch (Exception ex) 413 | { 414 | ErrorString += "\r\nError in SetValueArgument_Long: " + ex.Message; 415 | ErrorString += "\r\n" + ex.StackTrace; 416 | return false; 417 | } 418 | } 419 | 420 | /// 421 | /// Sets "Single" argument to the kernel. 422 | /// 423 | /// 0-based index of argument in argument list. 424 | /// Argument value as "Single". 425 | /// True, if the operation was successful, false otherwise. 426 | public bool SetValueArgument_Single(int argument_index, float value_single) 427 | { 428 | try 429 | { 430 | ComputeMemory varPointer = new ComputeBuffer(ComputeContext, ComputeMemoryFlags.ReadWrite, 1); 431 | 432 | variablePointers[argument_index] = varPointer; 433 | kernel.SetValueArgument(argument_index, value_single); 434 | 435 | return true; 436 | } 437 | catch (Exception ex) 438 | { 439 | ErrorString += "\r\nError in SetValueArgument_Single: " + ex.Message; 440 | ErrorString += "\r\n" + ex.StackTrace; 441 | return false; 442 | } 443 | } 444 | 445 | /// 446 | /// Sets "Double" argument to the kernel. 447 | /// 448 | /// 0-based index of argument in argument list. 449 | /// Argument value as "Double". 450 | /// True, if the operation was successful, false otherwise. 451 | public bool SetValueArgument_Double(int argument_index, double value_double) 452 | { 453 | try 454 | { 455 | ComputeMemory varPointer = new ComputeBuffer(ComputeContext, ComputeMemoryFlags.ReadWrite, 1); 456 | 457 | variablePointers[argument_index] = varPointer; 458 | kernel.SetValueArgument(argument_index, value_double); 459 | 460 | return true; 461 | } 462 | catch (Exception ex) 463 | { 464 | ErrorString += "\r\nError in SetValueArgument_Double: " + ex.Message; 465 | ErrorString += "\r\n" + ex.StackTrace; 466 | return false; 467 | } 468 | } 469 | 470 | #endregion SetArguments 471 | 472 | #region Execution 473 | 474 | /// 475 | /// Synchronous execution. 476 | /// 477 | /// Array of global work offset, or "null". 478 | /// Array of global work size, or "null". 479 | /// Array of local work size, or "null". 480 | /// False in case of error/exception. Otherwise true. 481 | public bool ExecuteSync(ref int[] globalWorkOffset, ref int[] globalWorkSize, ref int[] localWorkSize) 482 | { 483 | try 484 | { 485 | ExecutionCompleted = false; 486 | InitGlobalArrays(ref globalWorkOffset, ref globalWorkSize, ref localWorkSize); 487 | 488 | ComputeCommandQueue.Execute(kernel, _globalWorkOffset, _globalWorkSize, _localWorkSize, null); 489 | ComputeCommandQueue.Finish(); 490 | ExecutionCompleted = true; 491 | return true; 492 | } 493 | catch (Exception ex) 494 | { 495 | ErrorString += "\r\nError in ExecuteSync: " + ex.Message; 496 | ErrorString += "\r\n" + ex.StackTrace; 497 | return false; 498 | } 499 | } 500 | 501 | /// 502 | /// Execution in background. 503 | /// 504 | /// Array of global work offset, or "null". 505 | /// Array of global work size, or "null". 506 | /// Array of local work size, or "null". 507 | /// Thread priority as integer (0 - "Lowest", 1 - "BelowNormal", 2 - "Normal", 3 - "AboveNormal", 4 - "Highest"). 508 | /// False in case of error/exception. Otherwise true. 509 | public bool ExecuteBackground(ref int[] globalWorkOffset, ref int[] globalWorkSize, ref int[] localWorkSize, int threadPriority) 510 | { 511 | try 512 | { 513 | ExecutionCompleted = false; 514 | InitGlobalArrays(ref globalWorkOffset, ref globalWorkSize, ref localWorkSize); 515 | 516 | if (threadPriority < (int)ThreadPriority.Lowest || threadPriority > (int)ThreadPriority.Highest) 517 | { 518 | ErrorString += "\r\nError in ExecuteBackground: threadPriority = " + threadPriority + " is below 0 or above 4."; 519 | return false; 520 | } 521 | 522 | Thread executionThread = new Thread(ExecutionThread) 523 | { 524 | Name = "ExecutionThread", 525 | Priority = (ThreadPriority)threadPriority 526 | }; 527 | executionThread.Start(); 528 | return true; 529 | } 530 | catch (Exception ex) 531 | { 532 | ErrorString += "\r\nError in ExecuteBackground: " + ex.Message; 533 | ErrorString += "\r\n" + ex.StackTrace; 534 | return false; 535 | } 536 | } 537 | 538 | /// 539 | /// For asynchronous call from VBA we need an address of callback function because VBA can use events only 540 | /// from form/classes. 541 | /// 542 | /// Array of global work offset, or "null". 543 | /// Array of global work size, or "null". 544 | /// Array of local work size, or "null". 545 | /// Thread priority as integer (0 - "Lowest", 1 - "BelowNormal", 2 - "Normal", 3 - "AboveNormal", 4 - "Highest"). 546 | /// Callback to the VBA function. 547 | /// False in case of error/exception. Otherwise true. 548 | public bool ExecuteAsync(ref int[] globalWorkOffset, ref int[] globalWorkSize, ref int[] localWorkSize, int threadPriority, 549 | [MarshalAs(UnmanagedType.FunctionPtr)] ref Action callback) 550 | { 551 | try 552 | { 553 | this.callBack = callback; 554 | ExecuteBackground(ref globalWorkOffset, ref globalWorkSize, ref localWorkSize, threadPriority); 555 | return true; 556 | } 557 | catch (Exception ex) 558 | { 559 | ErrorString += "\r\nError in ExecuteAsync: " + ex.Message; 560 | ErrorString += "\r\n" + ex.StackTrace; 561 | return false; 562 | } 563 | } 564 | 565 | /// 566 | /// True, if execution is completed, false otherwise. 567 | /// 568 | public bool ExecutionCompleted { get; set; } = false; 569 | 570 | private void ExecutionThread() 571 | { 572 | ComputeCommandQueue.Execute(kernel, _globalWorkOffset, _globalWorkSize, _localWorkSize, null); 573 | ComputeCommandQueue.Finish(); 574 | ExecutionCompleted = true; 575 | callBack?.Invoke(); 576 | } 577 | 578 | private bool InitGlobalArrays(ref int[] globalWorkOffset, ref int[] globalWorkSize, ref int[] localWorkSize) 579 | { 580 | try 581 | { 582 | if (globalWorkOffset != null) 583 | { 584 | _globalWorkOffset = new long[globalWorkOffset.Length]; 585 | globalWorkOffset.CopyTo(_globalWorkOffset, 0); 586 | } 587 | if (globalWorkSize != null) 588 | { 589 | _globalWorkSize = new long[globalWorkSize.Length]; 590 | globalWorkSize.CopyTo(_globalWorkSize, 0); 591 | } 592 | if (localWorkSize != null) 593 | { 594 | _localWorkSize = new long[localWorkSize.Length]; 595 | localWorkSize.CopyTo(_localWorkSize, 0); 596 | } 597 | 598 | return true; 599 | } 600 | catch (Exception ex) 601 | { 602 | ErrorString += "\r\nError in InitGlobalArrays: " + ex.Message; 603 | ErrorString += "\r\n" + ex.StackTrace; 604 | return false; 605 | } 606 | } 607 | 608 | #endregion Execution 609 | 610 | #region GetArguments 611 | 612 | /// 613 | /// Reads an array of type "Long" from the device. 614 | /// 615 | /// 0-based index of argument in argument list. 616 | /// Array of "Long". 617 | /// False in case of error/exception. Otherwise true. 618 | public bool GetMemoryArgument_Long(int argument_index, ref int[] values) 619 | { 620 | try 621 | { 622 | unsafe 623 | { 624 | fixed (int* p = (int[])values) 625 | { 626 | IntPtr ptr = (IntPtr)p; 627 | ComputeCommandQueue.Read((ComputeBuffer)variablePointers[argument_index], true, 0L, values.Length, ptr, null); 628 | } 629 | } 630 | return true; 631 | } 632 | catch (Exception ex) 633 | { 634 | ErrorString += "\r\nError in GetMemoryArgument_Long: " + ex.Message; 635 | ErrorString += "\r\n" + ex.StackTrace; 636 | return false; 637 | } 638 | } 639 | 640 | /// 641 | /// Reads an array of type "Single" from the device. 642 | /// 643 | /// 0-based index of argument in argument list. 644 | /// Array of "Single". 645 | /// False in case of error/exception. Otherwise true. 646 | public bool GetMemoryArgument_Single(int argument_index, ref float[] values) 647 | { 648 | try 649 | { 650 | unsafe 651 | { 652 | fixed (float* p = (float[])values) 653 | { 654 | IntPtr ptr = (IntPtr)p; 655 | ComputeCommandQueue.Read((ComputeBuffer)variablePointers[argument_index], true, 0L, values.Length, ptr, null); 656 | } 657 | } 658 | return true; 659 | } 660 | catch (Exception ex) 661 | { 662 | ErrorString += "\r\nError in GetMemoryArgument_Single: " + ex.Message; 663 | ErrorString += "\r\n" + ex.StackTrace; 664 | return false; 665 | } 666 | } 667 | 668 | /// 669 | /// Reads an array of type "Double" from the device. 670 | /// 671 | /// 0-based index of argument in argument list. 672 | /// Array of "Double". 673 | /// False in case of error/exception. Otherwise true. 674 | public bool GetMemoryArgument_Double(int argument_index, ref double[] values) 675 | { 676 | try 677 | { 678 | unsafe 679 | { 680 | fixed (double* p = (double[])values) 681 | { 682 | IntPtr ptr = (IntPtr)p; 683 | ComputeCommandQueue.Read((ComputeBuffer)variablePointers[argument_index], true, 0L, values.Length, ptr, null); 684 | } 685 | } 686 | return true; 687 | } 688 | catch (Exception ex) 689 | { 690 | ErrorString += "\r\nError in GetMemoryArgument_Double: " + ex.Message; 691 | ErrorString += "\r\n" + ex.StackTrace; 692 | return false; 693 | } 694 | } 695 | 696 | #endregion GetArguments 697 | 698 | #region Destructors 699 | 700 | /// 701 | /// Disposes kernel memory variable. 702 | /// 703 | /// 0-based index of argument in argument list. 704 | /// True, if the operation was successful, false otherwise. 705 | public bool ReleaseMemObject(int argument_index) 706 | { 707 | try 708 | { 709 | variablePointers[argument_index].Dispose(); 710 | return true; 711 | } 712 | catch (Exception ex) 713 | { 714 | ErrorString += ex.Message; 715 | return false; 716 | } 717 | } 718 | 719 | /// 720 | /// Disposes kernel. 721 | /// 722 | /// True, if the operation was successful, false otherwise. 723 | public bool ReleaseKernel() 724 | { 725 | try 726 | { 727 | kernel.Dispose(); 728 | return true; 729 | } 730 | catch (Exception ex) 731 | { 732 | ErrorString += ex.Message; 733 | return false; 734 | } 735 | } 736 | 737 | /// 738 | /// Disposes ComputeProgram, ComputeCommandQueue and CommandQueue. 739 | /// 740 | /// True, if the operation was successful, false otherwise. 741 | public bool ReleaseProgram() 742 | { 743 | try 744 | { 745 | ComputeProgram.Dispose(); 746 | ComputeCommandQueue.Dispose(); 747 | ComputeContext.Dispose(); 748 | 749 | return true; 750 | } 751 | catch (Exception ex) 752 | { 753 | ErrorString += ex.Message; 754 | return false; 755 | } 756 | } 757 | 758 | #endregion Destructors 759 | 760 | /// 761 | /// Device type of initialized device ("GPU" / "CPU"). 762 | /// 763 | public string DeviceType { get; set; } = ""; 764 | 765 | /// 766 | /// Error string. 767 | /// 768 | public string ErrorString { get; set; } = ""; 769 | } 770 | } -------------------------------------------------------------------------------- /C#/ClooWrapperVBA/Device.cs: -------------------------------------------------------------------------------- 1 | using Cloo; 2 | using System; 3 | using System.ComponentModel; 4 | using System.Runtime.InteropServices; 5 | 6 | namespace ClooWrapperVBA 7 | { 8 | /// 9 | /// ProgramDevice interface. 10 | /// 11 | [ComVisible(true)] 12 | [Guid("B571086A-A2C7-4886-A7B7-5D109DF62207")] 13 | [InterfaceType(ComInterfaceType.InterfaceIsIDispatch)] 14 | public interface IDevice 15 | { 16 | /// 17 | /// Returns device name. 18 | /// 19 | [DispId(1), Description("Returns device name.")] 20 | string DeviceName { get; } 21 | 22 | /// 23 | /// Returns device type. () 24 | /// 25 | [DispId(2), Description("Returns device type.")] 26 | string DeviceType { get; } 27 | 28 | /// 29 | /// Returns vendor. 30 | /// 31 | [DispId(3), Description("Returns vendor.")] 32 | string DeviceVendor { get; } 33 | 34 | /// 35 | /// Returns availability state of device. 36 | /// 37 | [DispId(4), Description("Returns availability state of device.")] 38 | bool DeviceAvailable { get; } 39 | 40 | /// 41 | /// Returns device version. 42 | /// 43 | [DispId(5), Description("Returns device version.")] 44 | string DeviceVersion { get; } 45 | 46 | /// 47 | /// Returns device MaxComputeUnits. 48 | /// 49 | [DispId(6), Description("Returns device MaxComputeUnits.")] 50 | double MaxComputeUnits { get; } 51 | 52 | /// 53 | /// Returns device SingleCapabilites. 54 | /// 55 | [DispId(7), Description("Returns device SingleCapabilites.")] 56 | string SingleCapabilites { get; } 57 | 58 | /// 59 | /// Returns device AddressBits. 60 | /// 61 | [DispId(8), Description("Returns device AddressBits.")] 62 | int AddressBits { get; } 63 | 64 | /// 65 | /// Returns device CommandQueueFlags. 66 | /// 67 | [DispId(9), Description("Returns device CommandQueueFlags.")] 68 | string CommandQueueFlags { get; } 69 | 70 | /// 71 | /// Returns device CompilerAvailable. 72 | /// 73 | [DispId(10), Description("Returns device CompilerAvailable.")] 74 | bool CompilerAvailable { get; } 75 | 76 | /// 77 | /// Returns device DriverVersion. 78 | /// 79 | [DispId(11), Description("Returns device DriverVersion.")] 80 | string DriverVersion { get; } 81 | 82 | /// 83 | /// Returns device EndianLittle. 84 | /// 85 | [DispId(12), Description("Returns device EndianLittle.")] 86 | bool EndianLittle { get; } 87 | 88 | /// 89 | /// Returns device ErrorCorrectionSupport. 90 | /// 91 | [DispId(13), Description("Returns device ErrorCorrectionSupport.")] 92 | bool ErrorCorrectionSupport { get; } 93 | 94 | /// 95 | /// Returns device ExecutionCapabilities. 96 | /// 97 | [DispId(14), Description("Returns device ExecutionCapabilities.")] 98 | string ExecutionCapabilities { get; } 99 | 100 | /// 101 | /// Returns device Extensions. 102 | /// 103 | [DispId(15), Description("Returns device Extensions.")] 104 | string[] DeviceExtensions { get; } 105 | 106 | /// 107 | /// Returns device GlobalMemoryCacheLineSize. 108 | /// 109 | [DispId(16), Description("Returns device GlobalMemoryCacheLineSize.")] 110 | double GlobalMemoryCacheLineSize { get; } 111 | 112 | /// 113 | /// Returns device GlobalMemoryCacheSize. 114 | /// 115 | [DispId(17), Description("Returns device GlobalMemoryCacheSize.")] 116 | double GlobalMemoryCacheSize { get; } 117 | 118 | /// 119 | /// Returns device GlobalMemoryCacheType. 120 | /// 121 | [DispId(18), Description("Returns device GlobalMemoryCacheType.")] 122 | string GlobalMemoryCacheType { get; } 123 | 124 | /// 125 | /// Returns device GlobalMemorySize. 126 | /// 127 | [DispId(19), Description("Returns device GlobalMemorySize.")] 128 | double GlobalMemorySize { get; } 129 | 130 | /// 131 | /// Returns device HostUnifiedMemory. 132 | /// 133 | [DispId(20), Description("Returns device HostUnifiedMemory.")] 134 | bool HostUnifiedMemory { get; } 135 | 136 | /// 137 | /// Returns device Image2DMaxHeight. 138 | /// 139 | [DispId(21), Description("Returns device Image2DMaxHeight.")] 140 | double Image2DMaxHeight { get; } 141 | 142 | /// 143 | /// Returns device Image2DMaxWidth. 144 | /// 145 | [DispId(22), Description("Returns device Image2DMaxWidth.")] 146 | double Image2DMaxWidth { get; } 147 | 148 | /// 149 | /// Returns device Image3DMaxDepth. 150 | /// 151 | [DispId(23), Description("Returns device Image3DMaxDepth.")] 152 | double Image3DMaxDepth { get; } 153 | 154 | /// 155 | /// Returns device Image3DMaxHeight. 156 | /// 157 | [DispId(24), Description("Returns device Image3DMaxHeight.")] 158 | double Image3DMaxHeight { get; } 159 | 160 | /// 161 | /// Returns device Image3DMaxWidth. 162 | /// 163 | [DispId(25), Description("Returns device Image3DMaxWidth.")] 164 | double Image3DMaxWidth { get; } 165 | 166 | /// 167 | /// Returns device ImageSupport. 168 | /// 169 | [DispId(26), Description("Returns device ImageSupport.")] 170 | bool ImageSupport { get; } 171 | 172 | /// 173 | /// Returns device LocalMemorySize. 174 | /// 175 | [DispId(27), Description("Returns device LocalMemorySize.")] 176 | double LocalMemorySize { get; } 177 | 178 | /// 179 | /// Returns device LocalMemoryType. 180 | /// 181 | [DispId(28), Description("Returns device LocalMemoryType.")] 182 | string LocalMemoryType { get; } 183 | 184 | /// 185 | /// Returns device MaxClockFrequency. 186 | /// 187 | [DispId(29), Description("Returns device MaxClockFrequency.")] 188 | double MaxClockFrequency { get; } 189 | 190 | /// 191 | /// Returns device MaxConstantArguments. 192 | /// 193 | [DispId(30), Description("Returns device MaxConstantArguments.")] 194 | double MaxConstantArguments { get; } 195 | 196 | /// 197 | /// Returns device MaxConstantBufferSize. 198 | /// 199 | [DispId(31), Description("Returns device MaxConstantBufferSize.")] 200 | double MaxConstantBufferSize { get; } 201 | 202 | /// 203 | /// Returns device MaxMemoryAllocationSize. 204 | /// 205 | [DispId(32), Description("Returns device MaxMemoryAllocationSize.")] 206 | double MaxMemoryAllocationSize { get; } 207 | 208 | /// 209 | /// Returns device MaxParameterSize. 210 | /// 211 | [DispId(33), Description("Returns device MaxParameterSize.")] 212 | double MaxParameterSize { get; } 213 | 214 | /// 215 | /// Returns device MaxReadImageArguments. 216 | /// 217 | [DispId(34), Description("Returns device MaxReadImageArguments.")] 218 | double MaxReadImageArguments { get; } 219 | 220 | /// 221 | /// Returns device MaxSamplers. 222 | /// 223 | [DispId(35), Description("Returns device MaxSamplers.")] 224 | double MaxSamplers { get; } 225 | 226 | /// 227 | /// Returns device MaxWorkGroupSize. 228 | /// 229 | [DispId(36), Description("Returns device MaxWorkGroupSize.")] 230 | double MaxWorkGroupSize { get; } 231 | 232 | /// 233 | /// Returns device MaxWorkItemDimensions. 234 | /// 235 | [DispId(37), Description("Returns device MaxWorkItemDimensions.")] 236 | double MaxWorkItemDimensions { get; } 237 | 238 | /// 239 | /// Returns device MaxWorkItemSizes. 240 | /// 241 | [DispId(38), Description("Returns device MaxWorkItemSizes.")] 242 | double[] MaxWorkItemSizes { get; } 243 | 244 | /// 245 | /// Returns device MaxWriteImageArguments. 246 | /// 247 | [DispId(39), Description("Returns device MaxWriteImageArguments.")] 248 | double MaxWriteImageArguments { get; } 249 | 250 | /// 251 | /// Returns device MemoryBaseAddressAlignment. 252 | /// 253 | [DispId(40), Description("Returns device MemoryBaseAddressAlignment.")] 254 | double MemoryBaseAddressAlignment { get; } 255 | 256 | /// 257 | /// Returns device MinDataTypeAlignmentSize. 258 | /// 259 | [DispId(41), Description("Returns device MinDataTypeAlignmentSize.")] 260 | double MinDataTypeAlignmentSize { get; } 261 | 262 | /// 263 | /// Returns device NativeVectorWidthChar. 264 | /// 265 | [DispId(42), Description("Returns device NativeVectorWidthChar.")] 266 | double NativeVectorWidthChar { get; } 267 | 268 | /// 269 | /// Returns device NativeVectorWidthDouble. 270 | /// 271 | [DispId(43), Description("Returns device NativeVectorWidthDouble.")] 272 | double NativeVectorWidthDouble { get; } 273 | 274 | /// 275 | /// Returns device NativeVectorWidthFloat. 276 | /// 277 | [DispId(44), Description("Returns device NativeVectorWidthFloat.")] 278 | double NativeVectorWidthFloat { get; } 279 | 280 | /// 281 | /// Returns device NativeVectorWidthHalf. 282 | /// 283 | [DispId(45), Description("Returns device NativeVectorWidthHalf.")] 284 | double NativeVectorWidthHalf { get; } 285 | 286 | /// 287 | /// Returns device NativeVectorWidthInt. 288 | /// 289 | [DispId(46), Description("Returns device NativeVectorWidthInt.")] 290 | double NativeVectorWidthInt { get; } 291 | 292 | /// 293 | /// Returns device NativeVectorWidthLong. 294 | /// 295 | [DispId(47), Description("Returns device NativeVectorWidthLong.")] 296 | double NativeVectorWidthLong { get; } 297 | 298 | /// 299 | /// Returns device NativeVectorWidthShort. 300 | /// 301 | [DispId(48), Description("Returns device NativeVectorWidthShort.")] 302 | double NativeVectorWidthShort { get; } 303 | 304 | /// 305 | /// Returns device OpenCLCVersionString. 306 | /// 307 | [DispId(49), Description("Returns device OpenCLCVersionString.")] 308 | string OpenCLCVersionString { get; } 309 | 310 | /// 311 | /// Returns device PreferredVectorWidthChar. 312 | /// 313 | [DispId(50), Description("Returns device PreferredVectorWidthChar.")] 314 | double PreferredVectorWidthChar { get; } 315 | 316 | /// 317 | /// Returns device PreferredVectorWidthDouble. 318 | /// 319 | [DispId(51), Description("Returns device PreferredVectorWidthDouble.")] 320 | double PreferredVectorWidthDouble { get; } 321 | 322 | /// 323 | /// Returns device PreferredVectorWidthFloat. 324 | /// 325 | [DispId(52), Description("Returns device PreferredVectorWidthFloat.")] 326 | double PreferredVectorWidthFloat { get; } 327 | 328 | /// 329 | /// Returns device PreferredVectorWidthHalf. 330 | /// 331 | [DispId(53), Description("Returns device PreferredVectorWidthHalf.")] 332 | double PreferredVectorWidthHalf { get; } 333 | 334 | /// 335 | /// Returns device PreferredVectorWidthInt. 336 | /// 337 | [DispId(54), Description("Returns device PreferredVectorWidthInt.")] 338 | double PreferredVectorWidthInt { get; } 339 | 340 | /// 341 | /// Returns device PreferredVectorWidthLong. 342 | /// 343 | [DispId(55), Description("Returns device PreferredVectorWidthLong.")] 344 | double PreferredVectorWidthLong { get; } 345 | 346 | /// 347 | /// Returns device PreferredVectorWidthShort. 348 | /// 349 | [DispId(56), Description("Returns device PreferredVectorWidthShort.")] 350 | double PreferredVectorWidthShort { get; } 351 | 352 | /// 353 | /// Returns device Profile. 354 | /// 355 | [DispId(57), Description("Returns device Profile.")] 356 | string Profile { get; } 357 | 358 | /// 359 | /// Returns device ProfilingTimerResolution. 360 | /// 361 | [DispId(58), Description("Returns device ProfilingTimerResolution.")] 362 | double ProfilingTimerResolution { get; } 363 | 364 | /// 365 | /// Returns device VendorId. 366 | /// 367 | [DispId(59), Description("Returns device VendorId.")] 368 | double VendorId { get; } 369 | 370 | /// 371 | /// Error string. 372 | /// 373 | [DispId(60), Description("Error string.")] 374 | string ErrorString { get; set; } 375 | } 376 | 377 | /// 378 | /// Class Device (gets only configuration of device for defined platform). 379 | /// 380 | [Guid("F282B6B3-7F24-4E3A-AD14-FEEFF1E53513")] 381 | [ClassInterface(ClassInterfaceType.None)] 382 | [ComVisible(true)] 383 | public class Device : IDevice 384 | { 385 | private readonly int platformIndex = -1; 386 | private readonly int deviceIndex = -1; 387 | 388 | /// 389 | /// Error string. 390 | /// 391 | public string ErrorString { get; set; } 392 | 393 | /// 394 | /// Constructor of device. 395 | /// 396 | /// Platform index. 397 | /// Device index. 398 | public Device(int platformIndex, int deviceIndex) 399 | { 400 | ErrorString = ""; 401 | this.platformIndex = platformIndex; 402 | this.deviceIndex = deviceIndex; 403 | } 404 | 405 | /// 406 | /// Returns device name. 407 | /// 408 | public string DeviceName 409 | { 410 | get 411 | { 412 | try 413 | { 414 | return ComputePlatform.Platforms[platformIndex].Devices[deviceIndex].Name; 415 | } 416 | catch (Exception ex) 417 | { 418 | ErrorString += "\r\nError in DeviceName: " + ex.Message; 419 | return "Error"; 420 | } 421 | } 422 | } 423 | 424 | /// 425 | /// Returns device type. () 426 | /// 427 | public string DeviceType 428 | { 429 | get 430 | { 431 | try 432 | { 433 | switch ((uint)ComputePlatform.Platforms[platformIndex].Devices[deviceIndex].Type) 434 | { 435 | case 1: 436 | return "Default"; 437 | 438 | case 2: 439 | return "CPU"; 440 | 441 | case 4: 442 | return "GPU"; 443 | 444 | case 8: 445 | return "Accelerator"; 446 | 447 | case 4294967295: 448 | return "All"; 449 | } 450 | return ""; 451 | } 452 | catch (Exception ex) 453 | { 454 | ErrorString += "\r\nError in DeviceType: " + ex.Message; 455 | return "Error"; 456 | } 457 | } 458 | } 459 | 460 | /// 461 | /// Returns vendor. 462 | /// 463 | public string DeviceVendor 464 | { 465 | get 466 | { 467 | try 468 | { 469 | return ComputePlatform.Platforms[platformIndex].Devices[deviceIndex].Vendor; 470 | } 471 | catch (Exception ex) 472 | { 473 | ErrorString += "\r\nError in DeviceVendor: " + ex.Message; 474 | return "Error"; 475 | } 476 | } 477 | } 478 | 479 | /// 480 | /// Returns availability state of device. 481 | /// 482 | public bool DeviceAvailable 483 | { 484 | get 485 | { 486 | try 487 | { 488 | return ComputePlatform.Platforms[platformIndex].Devices[deviceIndex].Available; 489 | } 490 | catch (Exception ex) 491 | { 492 | ErrorString += "\r\nError in DeviceAvailable: " + ex.Message; 493 | return false; 494 | } 495 | } 496 | } 497 | 498 | /// 499 | /// Returns device version. 500 | /// 501 | public string DeviceVersion 502 | { 503 | get 504 | { 505 | try 506 | { 507 | return ComputePlatform.Platforms[platformIndex].Devices[deviceIndex].VersionString; 508 | } 509 | catch (Exception ex) 510 | { 511 | ErrorString += "\r\nError in DeviceVersion: " + ex.Message; 512 | return "Error"; 513 | } 514 | } 515 | } 516 | 517 | /// 518 | /// Returns device MaxComputeUnits. 519 | /// 520 | public double MaxComputeUnits 521 | { 522 | get 523 | { 524 | try 525 | { 526 | return (double)ComputePlatform.Platforms[platformIndex].Devices[deviceIndex].MaxComputeUnits; 527 | } 528 | catch (Exception ex) 529 | { 530 | ErrorString += "\r\nError in MaxComputeUnits: " + ex.Message; 531 | return -1; 532 | } 533 | } 534 | } 535 | 536 | /// 537 | /// Returns device SingleCapabilites. 538 | /// 539 | public string SingleCapabilites 540 | { 541 | get 542 | { 543 | try 544 | { 545 | return ComputePlatform.Platforms[platformIndex].Devices[deviceIndex].SingleCapabilites.ToString(); 546 | } 547 | catch (Exception ex) 548 | { 549 | ErrorString += "\r\nError in SingleCapabilites: " + ex.Message; 550 | return "Error"; 551 | } 552 | } 553 | } 554 | 555 | /// 556 | /// Returns device AddressBits. 557 | /// 558 | public int AddressBits 559 | { 560 | get 561 | { 562 | try 563 | { 564 | return (int)ComputePlatform.Platforms[platformIndex].Devices[deviceIndex].AddressBits; 565 | } 566 | catch (Exception ex) 567 | { 568 | ErrorString += "\r\nError in AddressBits: " + ex.Message; 569 | return -1; 570 | } 571 | } 572 | } 573 | 574 | /// 575 | /// Returns device CommandQueueFlags. 576 | /// 577 | public string CommandQueueFlags 578 | { 579 | get 580 | { 581 | try 582 | { 583 | return ComputePlatform.Platforms[platformIndex].Devices[deviceIndex].CommandQueueFlags.ToString(); 584 | } 585 | catch (Exception ex) 586 | { 587 | ErrorString += "\r\nError in CommandQueueFlags: " + ex.Message; 588 | return "Error"; 589 | } 590 | } 591 | } 592 | 593 | /// 594 | /// Returns device CompilerAvailable. 595 | /// 596 | public bool CompilerAvailable 597 | { 598 | get 599 | { 600 | try 601 | { 602 | return ComputePlatform.Platforms[platformIndex].Devices[deviceIndex].CompilerAvailable; 603 | } 604 | catch (Exception ex) 605 | { 606 | ErrorString += "\r\nError in CompilerAvailable: " + ex.Message; 607 | return false; 608 | } 609 | } 610 | } 611 | 612 | /// 613 | /// Returns device DriverVersion. 614 | /// 615 | public string DriverVersion 616 | { 617 | get 618 | { 619 | try 620 | { 621 | return ComputePlatform.Platforms[platformIndex].Devices[deviceIndex].DriverVersion; 622 | } 623 | catch (Exception ex) 624 | { 625 | ErrorString += "\r\nError in DriverVersion: " + ex.Message; 626 | return "Error"; 627 | } 628 | } 629 | } 630 | 631 | /// 632 | /// Returns device EndianLittle. 633 | /// 634 | public bool EndianLittle 635 | { 636 | get 637 | { 638 | try 639 | { 640 | return ComputePlatform.Platforms[platformIndex].Devices[deviceIndex].EndianLittle; 641 | } 642 | catch (Exception ex) 643 | { 644 | ErrorString += "\r\nError in EndianLittle: " + ex.Message; 645 | return false; 646 | } 647 | } 648 | } 649 | 650 | /// 651 | /// Returns device ErrorCorrectionSupport. 652 | /// 653 | public bool ErrorCorrectionSupport 654 | { 655 | get 656 | { 657 | try 658 | { 659 | return ComputePlatform.Platforms[platformIndex].Devices[deviceIndex].ErrorCorrectionSupport; 660 | } 661 | catch (Exception ex) 662 | { 663 | ErrorString += "\r\nError in ErrorCorrectionSupport: " + ex.Message; 664 | return false; 665 | } 666 | } 667 | } 668 | 669 | /// 670 | /// Returns device ExecutionCapabilities. 671 | /// 672 | public string ExecutionCapabilities 673 | { 674 | get 675 | { 676 | try 677 | { 678 | return ComputePlatform.Platforms[platformIndex].Devices[deviceIndex].ExecutionCapabilities.ToString(); 679 | } 680 | catch (Exception ex) 681 | { 682 | ErrorString += "\r\nError in ExecutionCapabilities: " + ex.Message; 683 | return "Error"; 684 | } 685 | } 686 | } 687 | 688 | /// 689 | /// Returns device Extensions. 690 | /// 691 | public string[] DeviceExtensions 692 | { 693 | get 694 | { 695 | try 696 | { 697 | string[] tmpStrings; 698 | if (ComputePlatform.Platforms[platformIndex].Extensions.Count == 0) 699 | { 700 | tmpStrings = new string[1]; 701 | } 702 | else 703 | { 704 | tmpStrings = new string[ComputePlatform.Platforms[platformIndex].Devices[deviceIndex].Extensions.Count]; 705 | ComputePlatform.Platforms[platformIndex].Devices[deviceIndex].Extensions.CopyTo(tmpStrings, 0); 706 | } 707 | 708 | return tmpStrings; 709 | } 710 | catch (Exception ex) 711 | { 712 | ErrorString += "\r\nError in DeviceExtensions: " + ex.Message; 713 | return null; 714 | } 715 | } 716 | } 717 | 718 | /// 719 | /// Returns device GlobalMemoryCacheLineSize. 720 | /// 721 | public double GlobalMemoryCacheLineSize 722 | { 723 | get 724 | { 725 | try 726 | { 727 | return ComputePlatform.Platforms[platformIndex].Devices[deviceIndex].GlobalMemoryCacheLineSize; 728 | } 729 | catch (Exception ex) 730 | { 731 | ErrorString += "\r\nError in GlobalMemoryCacheLineSize: " + ex.Message; 732 | return -1.0; 733 | } 734 | } 735 | } 736 | 737 | /// 738 | /// Returns device GlobalMemoryCacheSize. 739 | /// 740 | public double GlobalMemoryCacheSize 741 | { 742 | get 743 | { 744 | try 745 | { 746 | return ComputePlatform.Platforms[platformIndex].Devices[deviceIndex].GlobalMemoryCacheSize; 747 | } 748 | catch (Exception ex) 749 | { 750 | ErrorString += "\r\nError in GlobalMemoryCacheSize: " + ex.Message; 751 | return -1.0; 752 | } 753 | } 754 | } 755 | 756 | /// 757 | /// Returns device GlobalMemoryCacheType. 758 | /// 759 | public string GlobalMemoryCacheType 760 | { 761 | get 762 | { 763 | try 764 | { 765 | return ComputePlatform.Platforms[platformIndex].Devices[deviceIndex].GlobalMemoryCacheType.ToString(); 766 | } 767 | catch (Exception ex) 768 | { 769 | ErrorString += "\r\nError in GlobalMemoryCacheType: " + ex.Message; 770 | return "Error"; 771 | } 772 | } 773 | } 774 | 775 | /// 776 | /// Returns device GlobalMemorySize. 777 | /// 778 | public double GlobalMemorySize 779 | { 780 | get 781 | { 782 | try 783 | { 784 | return ComputePlatform.Platforms[platformIndex].Devices[deviceIndex].GlobalMemorySize; 785 | } 786 | catch (Exception ex) 787 | { 788 | ErrorString += "\r\nError in GlobalMemorySize: " + ex.Message; 789 | return -1.0; 790 | } 791 | } 792 | } 793 | 794 | /// 795 | /// Returns device HostUnifiedMemory. 796 | /// 797 | public bool HostUnifiedMemory 798 | { 799 | get 800 | { 801 | try 802 | { 803 | return ComputePlatform.Platforms[platformIndex].Devices[deviceIndex].HostUnifiedMemory; 804 | } 805 | catch (Exception ex) 806 | { 807 | ErrorString += "\r\nError in HostUnifiedMemory: " + ex.Message; 808 | return false; 809 | } 810 | } 811 | } 812 | 813 | /// 814 | /// Returns device Image2DMaxHeight. 815 | /// 816 | public double Image2DMaxHeight 817 | { 818 | get 819 | { 820 | try 821 | { 822 | return ComputePlatform.Platforms[platformIndex].Devices[deviceIndex].Image2DMaxHeight; 823 | } 824 | catch (Exception ex) 825 | { 826 | ErrorString += "\r\nError in Image2DMaxHeight: " + ex.Message; 827 | return -1.0; 828 | } 829 | } 830 | } 831 | 832 | /// 833 | /// Returns device Image2DMaxWidth. 834 | /// 835 | public double Image2DMaxWidth 836 | { 837 | get 838 | { 839 | try 840 | { 841 | return ComputePlatform.Platforms[platformIndex].Devices[deviceIndex].Image2DMaxWidth; 842 | } 843 | catch (Exception ex) 844 | { 845 | ErrorString += "\r\nError in Image2DMaxWidth: " + ex.Message; 846 | return -1.0; 847 | } 848 | } 849 | } 850 | 851 | /// 852 | /// Returns device Image3DMaxDepth. 853 | /// 854 | public double Image3DMaxDepth 855 | { 856 | get 857 | { 858 | try 859 | { 860 | return ComputePlatform.Platforms[platformIndex].Devices[deviceIndex].Image3DMaxDepth; 861 | } 862 | catch (Exception ex) 863 | { 864 | ErrorString += "\r\nError in Image3DMaxDepth: " + ex.Message; 865 | return -1.0; 866 | } 867 | } 868 | } 869 | 870 | /// 871 | /// Returns device Image3DMaxHeight. 872 | /// 873 | public double Image3DMaxHeight 874 | { 875 | get 876 | { 877 | try 878 | { 879 | return ComputePlatform.Platforms[platformIndex].Devices[deviceIndex].Image3DMaxHeight; 880 | } 881 | catch (Exception ex) 882 | { 883 | ErrorString += "\r\nError in Image3DMaxHeight: " + ex.Message; 884 | return -1.0; 885 | } 886 | } 887 | } 888 | 889 | /// 890 | /// Returns device Image3DMaxWidth. 891 | /// 892 | public double Image3DMaxWidth 893 | { 894 | get 895 | { 896 | try 897 | { 898 | return ComputePlatform.Platforms[platformIndex].Devices[deviceIndex].Image3DMaxWidth; 899 | } 900 | catch (Exception ex) 901 | { 902 | ErrorString += "\r\nError in Image3DMaxWidth: " + ex.Message; 903 | return -1.0; 904 | } 905 | } 906 | } 907 | 908 | /// 909 | /// Returns device ImageSupport. 910 | /// 911 | public bool ImageSupport 912 | { 913 | get 914 | { 915 | try 916 | { 917 | return ComputePlatform.Platforms[platformIndex].Devices[deviceIndex].ImageSupport; 918 | } 919 | catch (Exception ex) 920 | { 921 | ErrorString += "\r\nError in ImageSupport: " + ex.Message; 922 | return false; 923 | } 924 | } 925 | } 926 | 927 | /// 928 | /// Returns device LocalMemorySize. 929 | /// 930 | public double LocalMemorySize 931 | { 932 | get 933 | { 934 | try 935 | { 936 | return ComputePlatform.Platforms[platformIndex].Devices[deviceIndex].LocalMemorySize; 937 | } 938 | catch (Exception ex) 939 | { 940 | ErrorString += "\r\nError in LocalMemorySize: " + ex.Message; 941 | return -1.0; 942 | } 943 | } 944 | } 945 | 946 | /// 947 | /// Returns device LocalMemoryType. 948 | /// 949 | public string LocalMemoryType 950 | { 951 | get 952 | { 953 | try 954 | { 955 | return ComputePlatform.Platforms[platformIndex].Devices[deviceIndex].LocalMemoryType.ToString(); 956 | } 957 | catch (Exception ex) 958 | { 959 | ErrorString += "\r\nError in LocalMemoryType: " + ex.Message; 960 | return "Error"; 961 | } 962 | } 963 | } 964 | 965 | /// 966 | /// Returns device MaxClockFrequency. 967 | /// 968 | public double MaxClockFrequency 969 | { 970 | get 971 | { 972 | try 973 | { 974 | return ComputePlatform.Platforms[platformIndex].Devices[deviceIndex].MaxClockFrequency; 975 | } 976 | catch (Exception ex) 977 | { 978 | ErrorString += "\r\nError in MaxClockFrequency: " + ex.Message; 979 | return -1.0; 980 | } 981 | } 982 | } 983 | 984 | /// 985 | /// Returns device MaxConstantArguments. 986 | /// 987 | public double MaxConstantArguments 988 | { 989 | get 990 | { 991 | try 992 | { 993 | return ComputePlatform.Platforms[platformIndex].Devices[deviceIndex].MaxConstantArguments; 994 | } 995 | catch (Exception ex) 996 | { 997 | ErrorString += "\r\nError in MaxConstantArguments: " + ex.Message; 998 | return -1.0; 999 | } 1000 | } 1001 | } 1002 | 1003 | /// 1004 | /// Returns device MaxConstantBufferSize. 1005 | /// 1006 | public double MaxConstantBufferSize 1007 | { 1008 | get 1009 | { 1010 | try 1011 | { 1012 | return ComputePlatform.Platforms[platformIndex].Devices[deviceIndex].MaxConstantBufferSize; 1013 | } 1014 | catch (Exception ex) 1015 | { 1016 | ErrorString += "\r\nError in MaxConstantBufferSize: " + ex.Message; 1017 | return -1.0; 1018 | } 1019 | } 1020 | } 1021 | 1022 | /// 1023 | /// Returns device MaxMemoryAllocationSize. 1024 | /// 1025 | public double MaxMemoryAllocationSize 1026 | { 1027 | get 1028 | { 1029 | try 1030 | { 1031 | return ComputePlatform.Platforms[platformIndex].Devices[deviceIndex].MaxMemoryAllocationSize; 1032 | } 1033 | catch (Exception ex) 1034 | { 1035 | ErrorString += "\r\nError in MaxMemoryAllocationSize: " + ex.Message; 1036 | return -1.0; 1037 | } 1038 | } 1039 | } 1040 | 1041 | /// 1042 | /// Returns device MaxParameterSize. 1043 | /// 1044 | public double MaxParameterSize 1045 | { 1046 | get 1047 | { 1048 | try 1049 | { 1050 | return ComputePlatform.Platforms[platformIndex].Devices[deviceIndex].MaxParameterSize; 1051 | } 1052 | catch (Exception ex) 1053 | { 1054 | ErrorString += "\r\nError in MaxParameterSize: " + ex.Message; 1055 | return -1.0; 1056 | } 1057 | } 1058 | } 1059 | 1060 | /// 1061 | /// Returns device MaxReadImageArguments. 1062 | /// 1063 | public double MaxReadImageArguments 1064 | { 1065 | get 1066 | { 1067 | try 1068 | { 1069 | return ComputePlatform.Platforms[platformIndex].Devices[deviceIndex].MaxReadImageArguments; 1070 | } 1071 | catch (Exception ex) 1072 | { 1073 | ErrorString += "\r\nError in MaxReadImageArguments: " + ex.Message; 1074 | return -1.0; 1075 | } 1076 | } 1077 | } 1078 | 1079 | /// 1080 | /// Returns device MaxSamplers. 1081 | /// 1082 | public double MaxSamplers 1083 | { 1084 | get 1085 | { 1086 | try 1087 | { 1088 | return ComputePlatform.Platforms[platformIndex].Devices[deviceIndex].MaxSamplers; 1089 | } 1090 | catch (Exception ex) 1091 | { 1092 | ErrorString += "\r\nError in MaxSamplers: " + ex.Message; 1093 | return -1.0; 1094 | } 1095 | } 1096 | } 1097 | 1098 | /// 1099 | /// Returns device MaxWorkGroupSize. 1100 | /// 1101 | public double MaxWorkGroupSize 1102 | { 1103 | get 1104 | { 1105 | try 1106 | { 1107 | return ComputePlatform.Platforms[platformIndex].Devices[deviceIndex].MaxWorkGroupSize; 1108 | } 1109 | catch (Exception ex) 1110 | { 1111 | ErrorString += "\r\nError in MaxWorkGroupSize: " + ex.Message; 1112 | return -1.0; 1113 | } 1114 | } 1115 | } 1116 | 1117 | /// 1118 | /// Returns device MaxWorkItemDimensions. 1119 | /// 1120 | public double MaxWorkItemDimensions 1121 | { 1122 | get 1123 | { 1124 | try 1125 | { 1126 | return ComputePlatform.Platforms[platformIndex].Devices[deviceIndex].MaxWorkItemDimensions; 1127 | } 1128 | catch (Exception ex) 1129 | { 1130 | ErrorString += "\r\nError in MaxWorkItemDimensions: " + ex.Message; 1131 | return -1.0; 1132 | } 1133 | } 1134 | } 1135 | 1136 | /// 1137 | /// Returns device MaxWorkItemSizes. 1138 | /// 1139 | public double[] MaxWorkItemSizes 1140 | { 1141 | get 1142 | { 1143 | try 1144 | { 1145 | double[] maxWorkItemSizes = new double[ComputePlatform.Platforms[platformIndex].Devices[deviceIndex].MaxWorkItemSizes.Count]; 1146 | 1147 | for (int i = 0; i < maxWorkItemSizes.Length; i++) 1148 | { 1149 | maxWorkItemSizes[i] = ComputePlatform.Platforms[platformIndex].Devices[deviceIndex].MaxWorkItemSizes[i]; 1150 | } 1151 | 1152 | return maxWorkItemSizes; 1153 | } 1154 | catch (Exception ex) 1155 | { 1156 | ErrorString += "\r\nError in MaxWorkItemSizes: " + ex.Message; 1157 | return null; 1158 | } 1159 | } 1160 | } 1161 | 1162 | /// 1163 | /// Returns device MaxWriteImageArguments. 1164 | /// 1165 | public double MaxWriteImageArguments 1166 | { 1167 | get 1168 | { 1169 | try 1170 | { 1171 | return ComputePlatform.Platforms[platformIndex].Devices[deviceIndex].MaxWriteImageArguments; 1172 | } 1173 | catch (Exception ex) 1174 | { 1175 | ErrorString += "\r\nError in MaxWriteImageArguments: " + ex.Message; 1176 | return -1.0; 1177 | } 1178 | } 1179 | } 1180 | 1181 | /// 1182 | /// Returns device MemoryBaseAddressAlignment. 1183 | /// 1184 | public double MemoryBaseAddressAlignment 1185 | { 1186 | get 1187 | { 1188 | try 1189 | { 1190 | return ComputePlatform.Platforms[platformIndex].Devices[deviceIndex].MemoryBaseAddressAlignment; 1191 | } 1192 | catch (Exception ex) 1193 | { 1194 | ErrorString += "\r\nError in MemoryBaseAddressAlignment: " + ex.Message; 1195 | return -1.0; 1196 | } 1197 | } 1198 | } 1199 | 1200 | /// 1201 | /// Returns device MinDataTypeAlignmentSize. 1202 | /// 1203 | public double MinDataTypeAlignmentSize 1204 | { 1205 | get 1206 | { 1207 | try 1208 | { 1209 | return ComputePlatform.Platforms[platformIndex].Devices[deviceIndex].MinDataTypeAlignmentSize; 1210 | } 1211 | catch (Exception ex) 1212 | { 1213 | ErrorString += "\r\nError in MinDataTypeAlignmentSize: " + ex.Message; 1214 | return -1.0; 1215 | } 1216 | } 1217 | } 1218 | 1219 | /// 1220 | /// Returns device NativeVectorWidthChar. 1221 | /// 1222 | public double NativeVectorWidthChar 1223 | { 1224 | get 1225 | { 1226 | try 1227 | { 1228 | return ComputePlatform.Platforms[platformIndex].Devices[deviceIndex].NativeVectorWidthChar; 1229 | } 1230 | catch (Exception ex) 1231 | { 1232 | ErrorString += "\r\nError in NativeVectorWidthChar: " + ex.Message; 1233 | return -1.0; 1234 | } 1235 | } 1236 | } 1237 | 1238 | /// 1239 | /// Returns device NativeVectorWidthDouble. 1240 | /// 1241 | public double NativeVectorWidthDouble 1242 | { 1243 | get 1244 | { 1245 | try 1246 | { 1247 | return ComputePlatform.Platforms[platformIndex].Devices[deviceIndex].NativeVectorWidthDouble; 1248 | } 1249 | catch (Exception ex) 1250 | { 1251 | ErrorString += "\r\nError in NativeVectorWidthDouble: " + ex.Message; 1252 | return -1.0; 1253 | } 1254 | } 1255 | } 1256 | 1257 | /// 1258 | /// Returns device NativeVectorWidthFloat. 1259 | /// 1260 | public double NativeVectorWidthFloat 1261 | { 1262 | get 1263 | { 1264 | try 1265 | { 1266 | return ComputePlatform.Platforms[platformIndex].Devices[deviceIndex].NativeVectorWidthFloat; 1267 | } 1268 | catch (Exception ex) 1269 | { 1270 | ErrorString += "\r\nError in NativeVectorWidthFloat: " + ex.Message; 1271 | return -1.0; 1272 | } 1273 | } 1274 | } 1275 | 1276 | /// 1277 | /// Returns device NativeVectorWidthHalf. 1278 | /// 1279 | public double NativeVectorWidthHalf 1280 | { 1281 | get 1282 | { 1283 | try 1284 | { 1285 | return ComputePlatform.Platforms[platformIndex].Devices[deviceIndex].NativeVectorWidthHalf; 1286 | } 1287 | catch (Exception ex) 1288 | { 1289 | ErrorString += "\r\nError in NativeVectorWidthHalf: " + ex.Message; 1290 | return -1.0; 1291 | } 1292 | } 1293 | } 1294 | 1295 | /// 1296 | /// Returns device NativeVectorWidthInt. 1297 | /// 1298 | public double NativeVectorWidthInt 1299 | { 1300 | get 1301 | { 1302 | try 1303 | { 1304 | return ComputePlatform.Platforms[platformIndex].Devices[deviceIndex].NativeVectorWidthInt; 1305 | } 1306 | catch (Exception ex) 1307 | { 1308 | ErrorString += "\r\nError in NativeVectorWidthInt: " + ex.Message; 1309 | return -1.0; 1310 | } 1311 | } 1312 | } 1313 | 1314 | /// 1315 | /// Returns device NativeVectorWidthLong. 1316 | /// 1317 | public double NativeVectorWidthLong 1318 | { 1319 | get 1320 | { 1321 | try 1322 | { 1323 | return ComputePlatform.Platforms[platformIndex].Devices[deviceIndex].NativeVectorWidthLong; 1324 | } 1325 | catch (Exception ex) 1326 | { 1327 | ErrorString += "\r\nError in NativeVectorWidthLong: " + ex.Message; 1328 | return -1.0; 1329 | } 1330 | } 1331 | } 1332 | 1333 | /// 1334 | /// Returns device NativeVectorWidthShort. 1335 | /// 1336 | public double NativeVectorWidthShort 1337 | { 1338 | get 1339 | { 1340 | try 1341 | { 1342 | return ComputePlatform.Platforms[platformIndex].Devices[deviceIndex].NativeVectorWidthShort; 1343 | } 1344 | catch (Exception ex) 1345 | { 1346 | ErrorString += "\r\nError in NativeVectorWidthShort: " + ex.Message; 1347 | return -1.0; 1348 | } 1349 | } 1350 | } 1351 | 1352 | /// 1353 | /// Returns device OpenCLCVersionString. 1354 | /// 1355 | public string OpenCLCVersionString 1356 | { 1357 | get 1358 | { 1359 | try 1360 | { 1361 | return ComputePlatform.Platforms[platformIndex].Devices[deviceIndex].OpenCLCVersionString; 1362 | } 1363 | catch (Exception ex) 1364 | { 1365 | ErrorString += "\r\nError in OpenCLCVersionString: " + ex.Message; 1366 | return "Error"; 1367 | } 1368 | } 1369 | } 1370 | 1371 | /// 1372 | /// Returns device PreferredVectorWidthChar. 1373 | /// 1374 | public double PreferredVectorWidthChar 1375 | { 1376 | get 1377 | { 1378 | try 1379 | { 1380 | return ComputePlatform.Platforms[platformIndex].Devices[deviceIndex].PreferredVectorWidthChar; 1381 | } 1382 | catch (Exception ex) 1383 | { 1384 | ErrorString += "\r\nError in PreferredVectorWidthChar: " + ex.Message; 1385 | return -1.0; 1386 | } 1387 | } 1388 | } 1389 | 1390 | /// 1391 | /// Returns device PreferredVectorWidthDouble. 1392 | /// 1393 | public double PreferredVectorWidthDouble 1394 | { 1395 | get 1396 | { 1397 | try 1398 | { 1399 | return ComputePlatform.Platforms[platformIndex].Devices[deviceIndex].PreferredVectorWidthDouble; 1400 | } 1401 | catch (Exception ex) 1402 | { 1403 | ErrorString += "\r\nError in PreferredVectorWidthDouble: " + ex.Message; 1404 | return -1.0; 1405 | } 1406 | } 1407 | } 1408 | 1409 | /// 1410 | /// Returns device PreferredVectorWidthFloat. 1411 | /// 1412 | public double PreferredVectorWidthFloat 1413 | { 1414 | get 1415 | { 1416 | try 1417 | { 1418 | return ComputePlatform.Platforms[platformIndex].Devices[deviceIndex].PreferredVectorWidthFloat; 1419 | } 1420 | catch (Exception ex) 1421 | { 1422 | ErrorString += "\r\nError in PreferredVectorWidthFloat: " + ex.Message; 1423 | return -1.0; 1424 | } 1425 | } 1426 | } 1427 | 1428 | /// 1429 | /// Returns device PreferredVectorWidthHalf. 1430 | /// 1431 | public double PreferredVectorWidthHalf 1432 | { 1433 | get 1434 | { 1435 | try 1436 | { 1437 | return ComputePlatform.Platforms[platformIndex].Devices[deviceIndex].PreferredVectorWidthHalf; 1438 | } 1439 | catch (Exception ex) 1440 | { 1441 | ErrorString += "\r\nError in PreferredVectorWidthHalf: " + ex.Message; 1442 | return -1.0; 1443 | } 1444 | } 1445 | } 1446 | 1447 | /// 1448 | /// Returns device PreferredVectorWidthInt. 1449 | /// 1450 | public double PreferredVectorWidthInt 1451 | { 1452 | get 1453 | { 1454 | try 1455 | { 1456 | return ComputePlatform.Platforms[platformIndex].Devices[deviceIndex].PreferredVectorWidthInt; 1457 | } 1458 | catch (Exception ex) 1459 | { 1460 | ErrorString += "\r\nError in PreferredVectorWidthInt: " + ex.Message; 1461 | return -1.0; 1462 | } 1463 | } 1464 | } 1465 | 1466 | /// 1467 | /// Returns device PreferredVectorWidthLong. 1468 | /// 1469 | public double PreferredVectorWidthLong 1470 | { 1471 | get 1472 | { 1473 | try 1474 | { 1475 | return ComputePlatform.Platforms[platformIndex].Devices[deviceIndex].PreferredVectorWidthLong; 1476 | } 1477 | catch (Exception ex) 1478 | { 1479 | ErrorString += "\r\nError in PreferredVectorWidthLong: " + ex.Message; 1480 | return -1.0; 1481 | } 1482 | } 1483 | } 1484 | 1485 | /// 1486 | /// Returns device PreferredVectorWidthShort. 1487 | /// 1488 | public double PreferredVectorWidthShort 1489 | { 1490 | get 1491 | { 1492 | try 1493 | { 1494 | return ComputePlatform.Platforms[platformIndex].Devices[deviceIndex].PreferredVectorWidthShort; 1495 | } 1496 | catch (Exception ex) 1497 | { 1498 | ErrorString += "\r\nError in PreferredVectorWidthShort: " + ex.Message; 1499 | return -1.0; 1500 | } 1501 | } 1502 | } 1503 | 1504 | /// 1505 | /// Returns device Profile. 1506 | /// 1507 | public string Profile 1508 | { 1509 | get 1510 | { 1511 | try 1512 | { 1513 | return ComputePlatform.Platforms[platformIndex].Devices[deviceIndex].Profile; 1514 | } 1515 | catch (Exception ex) 1516 | { 1517 | ErrorString += "\r\nError in Profile: " + ex.Message; 1518 | return "Error"; 1519 | } 1520 | } 1521 | } 1522 | 1523 | /// 1524 | /// Returns device ProfilingTimerResolution. 1525 | /// 1526 | public double ProfilingTimerResolution 1527 | { 1528 | get 1529 | { 1530 | try 1531 | { 1532 | return ComputePlatform.Platforms[platformIndex].Devices[deviceIndex].ProfilingTimerResolution; 1533 | } 1534 | catch (Exception ex) 1535 | { 1536 | ErrorString += "\r\nError in ProfilingTimerResolution: " + ex.Message; 1537 | return -1.0; 1538 | } 1539 | } 1540 | } 1541 | 1542 | /// 1543 | /// Returns device VendorId. 1544 | /// 1545 | public double VendorId 1546 | { 1547 | get 1548 | { 1549 | try 1550 | { 1551 | return ComputePlatform.Platforms[platformIndex].Devices[deviceIndex].VendorId; 1552 | } 1553 | catch (Exception ex) 1554 | { 1555 | ErrorString += "\r\nError in VendorId: " + ex.Message; 1556 | return -1.0; 1557 | } 1558 | } 1559 | } 1560 | } 1561 | } --------------------------------------------------------------------------------