/// <summary> /// Constructs a new CPU runtime. /// </summary> /// <param name="context">The ILGPU context.</param> /// <param name="numThreads">The number of threads for paralllel processing.</param> /// <param name="warpSize">The number of threads per warp.</param> /// <param name="threadPriority">The thread priority of the execution threads.</param> /// <param name="flags">The compile-unit flags.</param> public CPUAccelerator( Context context, int numThreads, int warpSize, ThreadPriority threadPriority, CompileUnitFlags flags) : base(context, AcceleratorType.CPU) { if (numThreads < 1) { throw new ArgumentOutOfRangeException(nameof(numThreads)); } if (!CPURuntimeWarpContext.IsValidWarpSize(warpSize) || numThreads < warpSize || (numThreads % warpSize) != 0) { throw new ArgumentOutOfRangeException(nameof(warpSize)); } // Setup assembly and module builder for dynamic code generation var assemblyName = new AssemblyName(nameof(CPUAccelerator)); assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run); moduleBuilder = assemblyBuilder.DefineDynamicModule(nameof(CPUAccelerator)); NumThreads = numThreads; WarpSize = warpSize; threads = new Thread[numThreads]; finishedEvent = new Barrier(numThreads + 1); // Every thread requires a custom warp context. warpContexts = new CPURuntimeWarpContext[numThreads]; // The maximum number of thread groups that can be handled in parallel is // equal to the number of available threads in the worst case. groupContexts = new CPURuntimeGroupContext[numThreads]; for (int i = 0; i < numThreads; ++i) { warpContexts[i] = new CPURuntimeWarpContext(this); groupContexts[i] = new CPURuntimeGroupContext(this); var thread = threads[i] = new Thread(ExecuteThread) { IsBackground = true, Priority = threadPriority, }; thread.Name = "ILGPUExecutionThread" + i; thread.Start(i); } DefaultStream = CreateStream(); Name = nameof(CPUAccelerator); MemorySize = long.MaxValue; MaxGridSize = new Index3(int.MaxValue, int.MaxValue, int.MaxValue); MaxNumThreadsPerGroup = NumThreads; MaxSharedMemoryPerGroup = int.MaxValue; MaxConstantMemory = int.MaxValue; NumMultiprocessors = 1; MaxNumThreadsPerMultiprocessor = NumThreads; Bind(); InitBackend(CreateBackend(), flags); }
/// <summary> /// Initializes the internal execution engine. /// </summary> /// <param name="threadPriority">The desired thread priority.</param> private void InitExecutionEngine(ThreadPriority threadPriority) { threads = new Thread[NumThreads]; finishedEventPerMultiprocessor = new Barrier(NumMultiprocessors + 1); taskConcurrencyLimit = new SemaphoreSlim(1); // Setup all warp and group contexts int numWarpsPerMultiprocessor = MaxNumThreadsPerMultiprocessor / WarpSize; warpContexts = new CPURuntimeWarpContext[ NumMultiprocessors, numWarpsPerMultiprocessor]; groupContexts = new CPURuntimeGroupContext[NumMultiprocessors]; processorBarriers = new Barrier[NumMultiprocessors]; for (int i = 0; i < NumMultiprocessors; ++i) { for (int j = 0; j < numWarpsPerMultiprocessor; ++j) { warpContexts[i, j] = new CPURuntimeWarpContext( this, WarpSize); } groupContexts[i] = UsesSequentialExecution ? new SequentialCPURuntimeGroupContext(this) as CPURuntimeGroupContext : new ParallelCPURuntimeGroupContext(this); processorBarriers[i] = new Barrier(0); } // Instantiate all runtime threads Parallel.For(0, NumThreads, i => { var thread = threads[i] = new Thread(ExecuteThread) { IsBackground = true, Priority = threadPriority, }; thread.Name = $"ILGPU_{InstanceId}_CPU_{i}"; }); // Start or delay the creation of runtime threads if (NumThreads <= 32) { StartOrContinueRuntimeThreads(MaxNumThreadsPerMultiprocessor); } else { maxNumLaunchedThreadsPerGroup = 0; } }
/// <summary> /// Creates a new CPU multiprocessor. /// </summary> /// <param name="accelerator">The parent accelerator.</param> /// <param name="processorIndex">The index of the multiprocessor.</param> protected CPUMultiprocessor(CPUAccelerator accelerator, int processorIndex) { Accelerator = accelerator; ProcessorIndex = processorIndex; // Setup all warp and group contexts NumWarpsPerMultiprocessor = MaxNumThreadsPerMultiprocessor / WarpSize; warpContexts = new CPURuntimeWarpContext[NumWarpsPerMultiprocessor]; groupContext = new CPURuntimeGroupContext(this); for (int i = 0; i < NumWarpsPerMultiprocessor; ++i) { warpContexts[i] = new CPURuntimeWarpContext(this, WarpSize); } // Instantiate all runtime threads threads = new Thread[MaxNumThreadsPerMultiprocessor]; Parallel.For(0, MaxNumThreadsPerMultiprocessor, i => { var thread = threads[i] = new Thread(ExecuteThread) { IsBackground = true, Priority = Accelerator.ThreadPriority, }; thread.Name = $"ILGPU_{Accelerator.InstanceId}_CPU_{ProcessorIndex}_{i}"; }); // Start or delay the creation of runtime threads if (MaxNumThreadsPerMultiprocessor <= 32) { StartOrContinueRuntimeThreads(MaxNumThreadsPerMultiprocessor); } else { maxNumLaunchedThreadsPerGroup = 0; } }
/// <summary> /// Makes the current context the active one for this thread. /// </summary> internal void MakeCurrent() { currentContext = this; }