This project is read-only.

EnableMultithreading!!

Jul 25, 2012 at 1:09 PM

Hi,

I want to use GPU by too many threads (CPU threads).When I load modules by once thread and call "EnableMultithreading()" method then call a GPU module's by another thread a "ErrorInvalidContext" exception accrued.

Please guide me how to use GPU by multithreads.

Thank you..

Jul 31, 2012 at 3:10 PM

Hi,

I have the same problem:

  class Worker
  {
    public GPGPU gpu { get; set; }
    public int TID { get; set; }
    public void test(object stateObject)
    {
      int[] dev0 = gpu.Allocate<int>(512);
      int gridSize = 1;
      int blockSize = 512;
      gpu.Launch(gridSize, blockSize, "aaa", dev0);
      int[] host0 = new int[512];
      gpu.CopyFromDevice<int>(dev0, host0);
      gpu.FreeAll();

      Console.WriteLine(TID + " thread done.");

      Console.ReadKey();
    }
  }

  class Program
  {
    static void Main(string[] args)
    {
      GPGPU gpu = CudafyHost.GetDevice();
      CudafyModule module = CudafyModule.TryDeserialize();
      if (module == null || !module.TryVerifyChecksums())
      {
        module = CudafyTranslator.Cudafy();
        module.Serialize();
      }
      if (!gpu.IsModuleLoaded(module.Name))
      {
        gpu.LoadModule(module);
      }
      if (!gpu.IsMultithreadingEnabled)
      {
        gpu.EnableMultithreading();
      }
      

      List<Thread> threadArray = new List<Thread>();
      for (int i = 0; i < 10; i++)
      {
        Worker w = new Worker() { gpu = gpu, TID=i };
        Thread t = new Thread(w.test);
        t.Start();
        threadArray.Add(t);
      }
    }

    [Cudafy]
    public static void aaa(GThread thread, int[] a)
    {
      int tid = thread.threadIdx.x;
      a[tid] = 1;
    }

I wrote a simply progam: it has 10 CPU threads. I get "ErrorInvalidContext" exception too, at the allocation. How can i fix it?


Thank You!

Zollie

 

Aug 1, 2012 at 6:34 PM

You need to call EnableMultithreading on each GPU from main thread then call Lock/Unlock in each thread.  You then need to be sure that the correct context is current.  This is far better supported in the upcoming 1.10 release with its SetCurrentContext method (available already if you download and build sources). Please also look at MultithreadedTests.cs and MultiGPUTests.cs in the Cudafy.Host.UnitTests project.

Nick 

Aug 2, 2012 at 7:07 AM

Hi,

I have only one GPU. I solved this problem yesterday:

class Worker
  {
    public int TID { get; set; }
    public GASS.CUDA.Types.CUcontext ctx { get; set; }
  }

  class Program
  {
    static void test(object stateObject)
    {
      Worker w = (Worker)stateObject;
      int TID = w.TID;
      GASS.CUDA.Types.CUcontext ctx = w.ctx;
      GPGPU gpu = CudafyHost.GetDevice(CudafyModes.Target);
      ((CUDA)((CudaGPU)gpu).CudaDotNet).SetCurrentContext(ctx);

      int[] dev0 = gpu.Allocate<int>(512);
      int gridSize = 1;
      int blockSize = 512;
      gpu.Launch(gridSize, blockSize, "aaa", dev0);
      int[] host0 = new int[512];
      gpu.CopyFromDevice<int>(dev0, host0);
      gpu.Synchronize();  
      gpu.Free(dev0);

      Console.WriteLine(TID + " thread done.");
    }

    static void Main(string[] args)
    {
      CudaGPU gpu = (CudaGPU)CudafyHost.GetDevice(CudafyModes.Target);
      CudafyModule module = CudafyModule.TryDeserialize();
      if (module == null || !module.TryVerifyChecksums())
      {
        module = CudafyTranslator.Cudafy();
        module.Serialize();
      }
      if (!gpu.IsModuleLoaded(module.Name))
      {
        gpu.LoadModule(module, false);
      }

      //====================================Important code segment=================================
      GASS.CUDA.Types.CUcontext ctx = ((CUDA)gpu.CudaDotNet).CurrentContext;
      //====================================Important code segment=================================

      List<Thread> threadArray = new List<Thread>();

      for (int i = 0; i < 5; i++)
      {
        Worker w = new Worker() { TID = i, ctx = ctx };
        Thread t = new Thread(test);
        t.Start(w);
        threadArray.Add(t);
      }
      Console.ReadKey();
    }

    [Cudafy]
    public static void aaa(GThread thread, int[] a)
    {
      int tid = thread.threadIdx.x;
      a[tid] = 1;
    }

You need to load the correct context to use multithreading with one GPU.
You have to use CUDA.Net CUcontext for it. If you allocated more arrays, you have to use gpu.Free() for each array, because of gpu.FreeAll() method makes free all of the arrays, your input arrays to. It is problem, if your one thread just copied an array to device memory.

If you doesn't use this solution, your threads want to allocate the same time from the different contexts.

 

Thank You!

Zollie

(Sorry for my bad english)