Hey All,
Didn't know whether to put this here or in the C++ forum - here seems more appropriate. I've written a DLL to interface with Excel VBA code. The DLL works great, and most of the VBA works as well. The issue seems to be the last argument of the function call. No matter what value I put in there it passes this huge number to the C++ code instead of the value it's supposed to pass. If anyone can help me figure this out I'd appreciate it!
Here's the VBA:
Code:
Option Explicit
' Declare the LMM Function that's in the DLL
Declare PtrSafe Function GenCudaLMMPaths Lib "C:\Path to DLL\LMMExcel.dll" Alias "GenerateCUDALMMPaths" (xTimes#, xRates#, xVols#, xRData#, ByVal ArrLen&, ByVal NPaths&) As Long
' Generate LMM Paths on Click
Sub LMM_Click()
Dim Times#(), Rates#(), Vols#()
Dim x As Long
Dim y As Long
Dim rTimes As Range
Dim rRates As Range
Dim rVols As Range
Dim cell As Range
Dim sz&
sz = 15
' Resize
ReDim Times(sz), Rates(sz), Vols(sz)
' Fill in Data
Set rTimes = Sheets("Market").Range("C2:Q2")
x = 1
For Each cell In rTimes
Times(x) = cell.Value
x = x + 1
Next
Set rRates = Sheets("Market").Range("C5:Q5")
x = 1
For Each cell In rRates
Rates(x) = cell.Value
x = x + 1
Next
Set rVols = Sheets("Market").Range("C4:Q4")
x = 1
For Each cell In rVols
Vols(x) = cell.Value / 10000#
x = x + 1
Next
'Call the Function
Dim np&
np = Sheets("LMM").Range("C2").Value
Dim useCuda As Boolean
If Sheets("LMM").Range("C3").Value = "GPU" Then
useCuda = True
Else
useCuda = False
End If
Dim rData#()
Dim rValue
ReDim rData(np * sz * (sz + 3))
rValue = GenCudaLMMPaths(Times(1), Rates(1), Vols(1), rData(1), sz, np)
If rValue = -1 Then
'No CUDA Card
MsgBox ("Your system doesn't have a CUDA Enabled GPU")
ElseIf rValue = 1 Then
'Error Occurred
MsgBox ("An error occurred while trying to generate LMM paths")
ElseIf rValue = 0 Then
'Success
' Need to reformat return data
Dim fmtData()
ReDim fmtData(np * sz, sz)
Dim i, j, k
For i = 0 To np - 1
For j = 0 To np - 1
For k = 0 To np - 1
fmtData(((i * sz) + j) + 1, k + 1) = rData(((i * sz * sz) + (j * sz) + k) + 1)
Next k
Next j
Next i
'Fill in data
Sheets("LMM").Range("A8:K" & (np * sz)) = fmtData
Else
'Too many requested paths for this CUDA card
MsgBox ("In order to prevent GPU Lock-up, you cannot request more than " & rValue & " paths.")
Sheets("LMM").Range("C2").Value = rValue
End If
End Sub
Here's the DLL function:
Code:
int __stdcall GenerateCUDALMMPaths(double* arrTimes, double* arrRates, double* arrVols, double* retData, int ArrLength, int NPaths)
{
//Check if NPaths is too big
int maxSims = 0;
int NP = NPaths;
int ret = 0;
cudaDeviceProp cdp;
cudaGetDeviceProperties(&cdp, 0);
maxSims = (cdp.maxThreadsPerMultiProcessor * cdp.multiProcessorCount);
assert(false);
if(maxSims < NP)
{
return maxSims;
}
else if(maxSims == 0)
{
return -1;
}
std::vector<double> vTimes = std::vector<double>();
std::vector<double> vRates = std::vector<double>();
std::vector<double> vVols = std::vector<double>();
for(int i=0; i<ArrLength; i++)
{
vTimes.push_back(arrTimes[i]);
vRates.push_back(arrRates[i]);
vVols.push_back(arrVols[i]);
}
//Setup Return Array
double*** retArr = new double**[NP];
for(int i=0; i<NP; i++)
{
retArr[i] = new double*[ArrLength];
for(int j=0; j<ArrLength; j++)
{
retArr[i][j] = new double[ArrLength];
for(int k=0; k<ArrLength; k++)
{
retArr[i][j][k] = 0.0;
}
}
}
//Do CUDA Calc
bool result = LMM::generateLMMSamplePaths(vTimes, vRates, vVols, NP, retArr);
if(!result)
{
ret = 1;
}
//Process results to return
long h = 0;
for(int i=0; i<NP; i++)
{
for(int j=0; j<ArrLength; j++)
{
retData[h] = i;
++h;
retData[h] = j;
++h;
retData[h] = 0;
++h;
for(int k=0; k<ArrLength; k++)
{
retData[h] = retArr[i][j][k];
++h;
}
}
}
//Delete Results
for(int i=0; i<NP; i++)
{
for(int j=0; j<ArrLength; j++)
{
delete [] retArr[i][j];
}
delete [] retArr[i];
}
delete [] retArr;
//Return Results
return ret;
}
I realize the code's far from optimal and needs some cleanup, but first things first, getting the arguments passed correctly.
Thanks!