Ich habe versucht, ein Programm zu schreiben, das GPU verwendet, um ein Integral zu berechnen, das Gaussianquadratur numerische Integration verwendet. Ich habe versucht herauszufinden, warum dieses Programm nicht funktioniert. Ich denke, ich habe darauf hingewiesen, dass die Parameter, die im Funktionsaufruf d_one übergeben werden, nicht korrekt in den cuda c-Code kopiert werden. Ich bin mir nicht sicher, warum das passiert. Ich verbrachte so viel Zeit damit, es herauszufinden, aber ich konnte damit nicht weiterkommen.Variablen falsch kopiert von einem Fortran zu einem cuda c Programm
Hier sind die beiden Programme:
Das Fortran-Programm:
implicit real*8(a-h,o-z)
parameter (nlinx = 22) ! Total number of mesh regions
dimension sx(3*nlinx),swx(3*nlinx)
xa = 0.d0
xb = 5.d0
! In the following "nptx" is the total number of integration
! points. So, it is (nlinx * 3)
call meshwt1(xa,xb,nlinx,ntan,sx,swx,nptx)
ans0 = 0.d0
CAll d_one(sx, swx, nptx, ans0)
print *, ans0
stop
end
SUBROUTINE MESHWT1(A,B,N,NT,X,W,NTOT)
implicit real*8(a-h,o-z)
!3*N LINEAR POINTS FOR A TO B
!NT=0 OR 1, 3*NT TAN PTS FOR B TO INFINITY
!NTOT= 3*(N+NT)
DIMENSION X(*),W(*),G(3),GW(3)
G(1) = -0.7745966
G(2) = 0.0000000
G(3) = -G(1)
GW(2) = 0.8888888
GW(1) = 0.5555555
GW(3) = GW(1)
Y = N
DX = (B - A)/Y
K = 0
XA = A - DX
XB = A
DO 2 I = 1, N
XA = XA + DX
XB = XB + DX
DO 2 J = 1, 3
K = K + 1
X(K) = 0.5 * (XA + XB) + 0.5 * (XB - XA) * G(J)
2 W(K) = 0.5 * (XB - XA) * GW(J)
NTOT = K
IF(NT .EQ. 1) GO TO 3
GO TO 5
3 NTOT = K + 3
DO 4 J = 1, 3
K = K + 1
Y = (1.0 + G(J)) * 3.14159 * 0.25
X(K) = XB + DTAN(Y)
4 W(K) = GW(J) * 3.14159 * 0.25/(DCOS(Y)) ** 2
5 CONTINUE
RETURN
END
Das CUDA-Programm:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <cuda.h>
#include <cuda_runtime.h>
__global__ void loop_d(float *a, float *b, int N, float *ans)
{
__shared__ float temp[66];
int idx = threadIdx.x;
if (idx < 66)
{
temp[idx] = a[idx] * b[idx];
}
__syncthreads();
if (0 == idx)
{
float sum = 0.0;
for (int i=0; i < 66; i++)
{
sum += temp[i];
}
*ans = sum;
}
}
// The following function is called from the Fortran program
extern "C" void d_one_(float *a, float *b, int *Np, float *ans)
{
float *a_d, *b_d, *ans_d; // Declaring GPU Copies of the parameters passed
int blocks = 1; // Number of blocks used
int N = *Np; // Number of threads is determined by the parameter nptx passed from the Fortran program
// Allocating GPU memory
cudaMalloc((void **)&a_d, sizeof(float) * N);
cudaMalloc((void **)&b_d, sizeof(float) * N);
cudaMalloc((void **)&ans_d, sizeof(float));
// Copying information from CPU to GPU
cudaMemcpy(a_d, a, sizeof(float) * N, cudaMemcpyHostToDevice);
cudaMemcpy(b_d, b, sizeof(float) * N, cudaMemcpyHostToDevice);
cudaMemcpy(ans_d, ans, sizeof(float), cudaMemcpyHostToDevice);
// Calling the function on the GPU
loop_d<<< blocks, N >>>(a_d, b_d, N, ans_d);
cudaMemcpy(a, a_d, sizeof(float) * N, cudaMemcpyDeviceToHost);
cudaMemcpy(b, b_d, sizeof(float) * N, cudaMemcpyDeviceToHost);
cudaMemcpy(ans, ans_d, sizeof(float), cudaMemcpyDeviceToHost);
// Freeing GPU memory
cudaFree(a_d);
cudaFree(b_d);
cudaFree(ans_d);
return;
}
Die Ausgabe des Programms sollte 12,49999 sein. Ich bekomme eine Antwort in der Größenordnung von -314. Vielen Dank für Ihre Anregungen!
Jeder, der im 21. Jahrhundert implizit tippt, verdient all den Schmerz, der sich auf dem Schlagbaum auf sie niederschlägt. Es ist wahrscheinlich nicht die Quelle der Fehler, die Sie melden, aber es ist eine Frage von Sekunden, das Programm zu ändern, um die Möglichkeit auszuschließen, dass es die Quelle der Fehler ist. –
stimmen vollständig mit HPM überein. Der Grund, warum ich FORTRAN liebe, ist, dass jeder Code mit "IMPLICIT NONE" beginnen sollte. Imho das beste Motto überhaupt für die Codierung im Allgemeinen. – user463035818
Zumindest verwendet er eine explizite "implizite" Anweisung, die es offensichtlich macht, dass er versucht, 'echte * 8'-Variablen in' Floats' zu überführen. – tera