VRAM Allocator CUDA-Version

Basierend auf #10

C:
#include <stdio.h>
#include <CL/cl.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
    unsigned long long mem_size = 0;
    int err; // error code
    cl_device_id device_id; // compute device id
    cl_context context; // compute context
    cl_mem devTestMem;
    cl_uint num_devices=0;
    cl_platform_id platformId;
    cl_uint numPlatforms = 0;
    cl_int fillValue = 255;

    err = clGetPlatformIDs(1, &platformId, &numPlatforms);
    if (err != CL_SUCCESS)
    {
        //printf("Number of devices: %u\n", num_devices);
        printf("Error: Failed to getPlatforms!\n");
        return EXIT_FAILURE;
    }

    err = clGetDeviceIDs(platformId, CL_DEVICE_TYPE_GPU, 1, &device_id, &num_devices);

    if (err != CL_SUCCESS)
    {
        printf("Error: Failed to create a device group!\n");

        if (err == CL_INVALID_PLATFORM) {
            printf("Error: CL_INVALID_PLATFORM\n");
        }
        if (err == CL_INVALID_DEVICE_TYPE) {
            printf("Error: CL_INVALID_DEVICE_TYPE\n");
        }
        if (err == CL_INVALID_VALUE) {
            printf("Error: CL_INVALID_VALUE\n");
        }
        if (err == CL_DEVICE_NOT_FOUND) {
            printf("Error: CL_DEVICE_NOT_FOUND\n");
        }
        return EXIT_FAILURE;
    }

    context = clCreateContext(0, 1, &device_id, NULL, NULL, &err);

    if (err != CL_SUCCESS)
    {
        printf("Error: Failed to create a compute context!\n");
        return EXIT_FAILURE;
    }

    // get amount of memory to allocate in MB, default to 256
    if (argc < 2 || sscanf(argv[1], " %llu", &mem_size) != 1) {
        mem_size = 256;
    }
    mem_size *= 1024 * 1024;; // convert MB to bytes

    // allocate GPU memory
    devTestMem = clCreateBuffer(context, CL_MEM_READ_WRITE, mem_size, NULL, &err);

    if (err!=CL_SUCCESS) {
        printf("Error, could not allocate %llu bytes.\n", mem_size);
        return EXIT_FAILURE;
    }

    auto queue= clCreateCommandQueue(context, device_id, !CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE, &err);
    
    if (err != CL_SUCCESS) {
        printf("Error, could not create queue\n");
        return EXIT_FAILURE;
    }
    
    // Fill the buffer with the initial value
    err = clEnqueueFillBuffer(queue, devTestMem, &fillValue, sizeof(cl_int), 0, mem_size, 0, NULL, NULL);
    
    if (err != CL_SUCCESS) {
        printf("Error, could not fill buffer\n");
        if (err== CL_INVALID_COMMAND_QUEUE) { printf("CL_INVALID_COMMAND_QUEUE\n"); }
        if (err == CL_INVALID_CONTEXT) { printf("CL_INVALID_CONTEXT\n"); }
        if (err == CL_INVALID_MEM_OBJECT) { printf("CL_INVALID_MEM_OBJECT \n"); }
        if (err == CL_INVALID_VALUE) { printf("CL_INVALID_VALUE\n"); }
        if (err == CL_INVALID_EVENT_WAIT_LIST) { printf("CL_INVALID_EVENT_WAIT_LIST \n"); }
        if (err == CL_MISALIGNED_SUB_BUFFER_OFFSET) { printf("CL_MISALIGNED_SUB_BUFFER_OFFSET \n"); }
        if (err == CL_MEM_OBJECT_ALLOCATION_FAILURE) { printf("CL_MEM_OBJECT_ALLOCATION_FAILURE \n"); }
        if (err == CL_OUT_OF_RESOURCES) { printf("CL_OUT_OF_RESOURCES \n"); }
        if (err == CL_OUT_OF_HOST_MEMORY) { printf("CL_OUT_OF_HOST_MEMORY \n"); }

        return EXIT_FAILURE;
    }
    
    clFinish(queue);
    
    // wait for a key press
    printf("Press return to exit...\n");
    getchar();

    // free GPU memory and exit
    clReleaseMemObject(devTestMem);
    clReleaseContext(context);
    return 0;
}
 
  • Gefällt mir
Reaktionen: ZeroStrat
  1. Ist gestern Abend quick and dirty entstanden.
  2. Würde ich gerne noch einen Kernel auf den GPU starten und beobachten was dann passiert.
 
Ich habe einen sehr ähnlichen Code mittlerweile, der lauffähig ist. Allerdings wird nicht wirklich was allokiert. Reicht ein Fill mit 0 nicht??
 
Ja, das habe ich auch gemerkt. Trozdem wird nichts allokiert. Der CUDA Code ist deutlich einfacher!
 
CUDA streikt aber auf AMD Karten. ;)
Naja, heute Abend wird sich am Code aber auch nichts mehr ändern.
 
Bei mir funktioniert es nun auf der Radeon VII. Ich habe die Platformen auswählbar gemacht. Ist allerdings noch hart verdrahtet im Code. Außerdem bin ich auf OCL 2.0 gegangen (clCreateContextFromType).

Code:
#include <stdio.h>
#include <CL/cl.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
    unsigned long mem_size = 0;
    cl_int err; // error code
    cl_device_id device_id; // compute device id
    cl_context context; // compute context
    cl_mem devTestMem;
    cl_uint num_devices;
    cl_platform_id platformId;
    cl_uint numPlatforms = 0;
    cl_uint ret_num_devices;
    cl_uint ret_num_platforms;
    cl_int fillValue = 255;

    // query the number of platforms
    err = clGetPlatformIDs(0, NULL, &numPlatforms);

    if (err != CL_SUCCESS)
    {
        printf("Error: Failed to number of platforms!\n");
        return EXIT_FAILURE;
    }

    // now get all the platform IDs
    cl_platform_id* platforms = new cl_platform_id[numPlatforms];
    err = clGetPlatformIDs(numPlatforms, platforms, &ret_num_platforms);

    if (err != CL_SUCCESS)
    {
        printf("Error: Failed to get platform IDs!\n");
        return EXIT_FAILURE;
    }

    // set platform property - we just pick the first one
    cl_context_properties properties[] = { CL_CONTEXT_PLATFORM, (int)platforms[0], 0 };

    err = clGetDeviceIDs(platforms[0], CL_DEVICE_TYPE_GPU, 1, &device_id, &ret_num_devices);

    if (err != CL_SUCCESS)
    {
        printf("Error: Failed to create a device group!\n");

        if (err == CL_INVALID_PLATFORM) {
            printf("Error: CL_INVALID_PLATFORM\n");
        }
        if (err == CL_INVALID_DEVICE_TYPE) {
            printf("Error: CL_INVALID_DEVICE_TYPE\n");
        }
        if (err == CL_INVALID_VALUE) {
            printf("Error: CL_INVALID_VALUE\n");
        }
        if (err == CL_DEVICE_NOT_FOUND) {
            printf("Error: CL_DEVICE_NOT_FOUND\n");
        }
        return EXIT_FAILURE;
    }

    // get amount of memory to allocate in MB, default to 256
    if (argc < 2 || sscanf_s(argv[1], " %llu", &mem_size) != 1) {
        mem_size = 256;
    }
    mem_size *= 1024 * 1024; // convert MB to bytes

    context = clCreateContextFromType(properties, CL_DEVICE_TYPE_GPU, NULL, NULL, &err);

    if (!context)
    {
        printf("Error: Failed to create a compute context!\n");
        return 1;
    }

    // allocate GPU memory
    devTestMem = clCreateBuffer(context, CL_MEM_READ_WRITE, mem_size, NULL, &err);

    if (err != CL_SUCCESS) {
        printf("Error, could not allocate %llu bytes.\n", mem_size);
        return EXIT_FAILURE;
    }

    cl_command_queue command_queue = clCreateCommandQueueWithProperties(context, device_id, 0, &err);

    if (err != CL_SUCCESS) {
        printf("Error, could not create queue\n");
        return EXIT_FAILURE;
    }

    // Fill the buffer with the initial value
    err = clEnqueueFillBuffer(command_queue, devTestMem, &fillValue, sizeof(cl_int), 0, mem_size, 0, NULL, NULL);

    if (err != CL_SUCCESS) {
        printf("Error, could not fill buffer\n");
        if (err == CL_INVALID_COMMAND_QUEUE) { printf("CL_INVALID_COMMAND_QUEUE\n"); }
        if (err == CL_INVALID_CONTEXT) { printf("CL_INVALID_CONTEXT\n"); }
        if (err == CL_INVALID_MEM_OBJECT) { printf("CL_INVALID_MEM_OBJECT \n"); }
        if (err == CL_INVALID_VALUE) { printf("CL_INVALID_VALUE\n"); }
        if (err == CL_INVALID_EVENT_WAIT_LIST) { printf("CL_INVALID_EVENT_WAIT_LIST \n"); }
        if (err == CL_MISALIGNED_SUB_BUFFER_OFFSET) { printf("CL_MISALIGNED_SUB_BUFFER_OFFSET \n"); }
        if (err == CL_MEM_OBJECT_ALLOCATION_FAILURE) { printf("CL_MEM_OBJECT_ALLOCATION_FAILURE \n"); }
        if (err == CL_OUT_OF_RESOURCES) { printf("CL_OUT_OF_RESOURCES \n"); }
        if (err == CL_OUT_OF_HOST_MEMORY) { printf("CL_OUT_OF_HOST_MEMORY \n"); }

        return EXIT_FAILURE;
    }

    clFinish(command_queue);

    // wait for a key press
    printf("Press return to exit...\n");
    getchar();

    // free memory and exit
    free(platforms);
    clReleaseMemObject(devTestMem);
    clReleaseContext(context);
    return 0;
}

Edit: Obwohl ich "$(AMDAPPSDKROOT)/lib/x86_64" verwende als zusätzliches Verzeichnis kann ich die 64bit Variante nicht kompilieren. Warum?
 

Anhänge

  • After_Alloc.png
    After_Alloc.png
    194,3 KB · Aufrufe: 491
  • Before_Alloc.png
    Before_Alloc.png
    209,7 KB · Aufrufe: 489
Zuletzt bearbeitet von einem Moderator:
Im Moment sieht's so aus, als könne ich mit der 32bit Variante nur 2GB Speicher allokieren. Es kann natürlich auch sein, dass sich das mit 64bit nicht ändert.
 
Zuletzt bearbeitet von einem Moderator:
Hi,

die 64 Bit Version ließ sich ohne Probleme compilieren und befindet sich im Anhang.

Edit: Die kompilierte Version wurde entfernt, da diese fehlerhaft war.
 
Zuletzt bearbeitet:
Funktioniert der Teil auch im grünen Lager?
Bei mir leider nicht. Komme ohne Fehlermeldung, und ohne das sich was ändert an den Prompt zurück.
 
Das Tool sollte auch im grünen Lager funktionieren.
Das Binary wurde von mir aber gerade entfernt, da es einen Bug hatte.
 
Hallo32 schrieb:
die 64 Bit Version ließ sich ohne Probleme compilieren und befindet sich im Anhang.

Wie kompilierst du? Ich verwende das Visual Studio und diese Lib: https://github.com/GPUOpen-LibrariesAndSDKs/OCL-SDK/releases

Das ist übrigens nicht kompatibel mit Nvidia. Für Nvidia* Karten sollten man die OpenCL.lib verwenden, die mit dem Treiber ausgeliefert wird. Siehe diese sehr empfehlenswerte Anleitung hier: https://streamhpc.com/blog/2015-03-...Y6q3VHMClVb0nPQMz8P3qnVgpO2sHU82jTkA06slGY91g

* Je nachdem, was dann zur Laufzeit referenziert wird, ist es wohl doch kompatibel mit Nvidia Karten.

Edit: Hab eine lauffähige 64bit Version eingefügt. Kann das mal bitte jemand testen. Läuft sogar auf meiner Quadro.

Hinweis: Die Version läuft bisher nur auf meinem System!

Anleitung:
  1. Navigiere in einer Konsole zum Ordner der AMD_VRAM_Allocator.exe
  2. Rufe die Test-App über "AMD_VRAM_Allocator.exe 1000" auf. 1000 ein Beispiel und entspricht 1GB.
Falls es auf AMD Karten nicht läuft, dieses SDK installieren: https://github.com/GPUOpen-LibrariesAndSDKs/OCL-SDK/releases
 

Anhänge

  • AMD_VRAM_Allocator.zip
    79,3 KB · Aufrufe: 469
  • Quadro_VRAM_after_allocation.png
    Quadro_VRAM_after_allocation.png
    57,6 KB · Aufrufe: 481
  • Quadro_VRAM_before_allocation.png
    Quadro_VRAM_before_allocation.png
    59,9 KB · Aufrufe: 487
Zuletzt bearbeitet von einem Moderator:
Startet bei mir mit und ohne dem SDK auf einer Vega 56 19.2.3 @windows 10 1809 x64 (egal ob User oder Admin) - beendet sich jedoch selbst ohne Fehlermeldung und alloziert keinen Speicher.
 
Ist bei mir das gleiche.
 
iamunknown schrieb:
Startet bei mir mit und ohne dem SDK auf einer Vega 56 19.2.3 @windows 10 1809 x64 (egal ob User oder Admin) - beendet sich jedoch selbst ohne Fehlermeldung und alloziert keinen Speicher.

Erstelle mal bitte folgende Umgebungsvariable:

AMDAPPSDKROOT
C:\Program Files (x86)\OCL_SDK_Light

EnVar_AMD_OpenCL.png


Kannst du in der Konsole mit "set" überprüfen, ob die danach tatsächlich existiert.

Edit: Eigentlich ist das Blödsinn mit der Lib. Das ist ja eine Programmierbibliothek. Die OpenCL.dll muss über den jeweiligen Treiber bereitgestellt werden.
 
Zuletzt bearbeitet von einem Moderator:
Zurück
Oben