Added new giteaaction

This commit is contained in:
2025-09-11 10:54:34 +09:00
parent 3923682b5e
commit 02e173415e
14 changed files with 223 additions and 70 deletions

View File

@@ -0,0 +1,53 @@
name: Publish NuGet Packages
on:
push:
tags:
- 'v*.*.*' # Trigger only on semantic version tags
jobs:
publish:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v3
- name: Setup .NET
uses: actions/setup-dotnet@v3
with:
dotnet-version: 9.0.x
- name: Restore dependencies
run: dotnet restore
- name: Build all projects
run: dotnet build -c Release
- name: Pack all projects
run: |
VERSION=$(dotnet msbuild "$projname/$projname.csproj" \
-nologo -v:q -t:GetProperty -p:PropertyName=PackageVersion)
for projfile in $(find . -name "*.csproj"); do
packable=$(dotnet msbuild $projfile -t:GetProperty -p:PropertyName=IsPackable -nologo -v:q)
if [ "$packable" = "true" ]; then
dotnet pack $proj/$proj.csproj -c Release
fi
done
- name: Publish all packages
env:
NUGET_API_KEY: ${{ secrets.GITEA_TOKEN }}
run: |
VERSION=$(dotnet msbuild "$projname/$projname.csproj" \
-nologo -v:q -t:GetProperty -p:PropertyName=PackageVersion)
for projfile in $(find . -name "*.csproj"); do
packable=$(dotnet msbuild $projfile -t:GetProperty -p:PropertyName=IsPackable -nologo -v:q)
if [ "$packable" = "true" ]; then
projname=$(basename $projfile .csproj)
dotnet pack $projfile -c Release
dotnet nuget push $projname/bin/Release/$projname.$VERSION.nupkg \
--source "https://git.personalnas.com/api/packages/Misaki/nuget/index.json" \
--api-key $NUGET_API_KEY
fi
done

View File

@@ -9,6 +9,7 @@
<Version>1.0.0</Version> <Version>1.0.0</Version>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<TargetFramework>net9.0</TargetFramework> <TargetFramework>net9.0</TargetFramework>
<IsPackable>false</IsPackable>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)'=='Release'"> <PropertyGroup Condition="'$(Configuration)'=='Release'">

View File

@@ -1,2 +1,2 @@
global using unsafe JobExecuteFunc = delegate*<void*, ref Misaki.HighPerformance.Jobs.JobRanges, ref int, int, bool>; global using unsafe JobExecutionFunc = delegate*<void*, ref Misaki.HighPerformance.Jobs.JobRanges, ref int, int, bool>;

View File

@@ -1,11 +1,29 @@
namespace Misaki.HighPerformance.Jobs; namespace Misaki.HighPerformance.Jobs;
public enum JobStatus /// <summary>
/// The state of a job in its lifecycle.
/// </summary>
public enum JobState
{ {
/// <summary>
/// The job is in an invalid state, indicating an error or uninitialized state. Or already finished the execution and cleaned up by the system.
/// </summary>
Invalid = -1, Invalid = -1,
/// <summary>
/// The job has been created but not yet scheduled for execution.
/// </summary>
Created = 0, Created = 0,
/// <summary>
/// The job is scheduled and waiting to be executed.
/// </summary>
Scheduled = 1, Scheduled = 1,
/// <summary>
/// The job is currently being executed.
/// </summary>
Running = 2, Running = 2,
/// <summary>
/// The job has completed execution.
/// </summary>
Completed = 3 Completed = 3
} }
@@ -21,9 +39,9 @@ internal unsafe struct JobInfo
public JobRanges jobRanges; public JobRanges jobRanges;
public void* pJobData; public void* pJobData;
public JobExecuteFunc executeDelegate; public JobExecutionFunc pExecutionFunc;
public JobStatus status; public JobState state;
public int remainingBatches; public int remainingBatches;
public int threadIndex; // The preferred thread index to run this job on, -1 means any thread public int threadIndex; // The preferred thread index to run this job on, -1 means any thread

View File

@@ -71,7 +71,7 @@ public unsafe sealed class JobScheduler : IDisposable
if (exist && Volatile.Read(ref jobInfo.dependencyCount) == 0) if (exist && Volatile.Read(ref jobInfo.dependencyCount) == 0)
{ {
if (Interlocked.CompareExchange(ref jobInfo.status, JobStatus.Scheduled, JobStatus.Created) != JobStatus.Created) if (Interlocked.CompareExchange(ref jobInfo.state, JobState.Scheduled, JobState.Created) != JobState.Created)
{ {
return; return;
} }
@@ -117,7 +117,7 @@ public unsafe sealed class JobScheduler : IDisposable
lock (_lock) lock (_lock)
{ {
ref var depJobInfo = ref _jobInfoPool.GetElementReferenceAt(dependency._id, dependency._generation, out var exist); ref var depJobInfo = ref _jobInfoPool.GetElementReferenceAt(dependency._id, dependency._generation, out var exist);
if (!exist || Volatile.Read(ref Unsafe.As<JobStatus, int>(ref depJobInfo.status)) == (int)JobStatus.Completed) if (!exist || Volatile.Read(ref Unsafe.As<JobState, int>(ref depJobInfo.state)) == (int)JobState.Completed)
{ {
continue; continue;
} }
@@ -197,7 +197,7 @@ public unsafe sealed class JobScheduler : IDisposable
return; return;
} }
if (Interlocked.CompareExchange(ref info.status, JobStatus.Completed, JobStatus.Running) != JobStatus.Running) if (Interlocked.CompareExchange(ref info.state, JobState.Completed, JobState.Running) != JobState.Running)
{ {
return; return;
} }
@@ -256,7 +256,7 @@ public unsafe sealed class JobScheduler : IDisposable
var jobInfo = new JobInfo var jobInfo = new JobInfo
{ {
pJobData = jobData, pJobData = jobData,
executeDelegate = &JobExecutor.Execute<T>, pExecutionFunc = &JobExecutor.Execute<T>,
remainingBatches = 1, remainingBatches = 1,
threadIndex = threadIndex, threadIndex = threadIndex,
@@ -311,7 +311,7 @@ public unsafe sealed class JobScheduler : IDisposable
var jobInfo = new JobInfo var jobInfo = new JobInfo
{ {
pJobData = jobData, pJobData = jobData,
executeDelegate = &JobExecutor.ExecuteParallel<T>, pExecutionFunc = &JobExecutor.ExecuteParallel<T>,
remainingBatches = totalBatches, remainingBatches = totalBatches,
threadIndex = threadIndex, threadIndex = threadIndex,
@@ -352,7 +352,7 @@ public unsafe sealed class JobScheduler : IDisposable
var jobInfo = new JobInfo var jobInfo = new JobInfo
{ {
pJobData = null, pJobData = null,
executeDelegate = null, pExecutionFunc = null,
remainingBatches = 1, remainingBatches = 1,
threadIndex = -1, threadIndex = -1,
@@ -367,22 +367,22 @@ public unsafe sealed class JobScheduler : IDisposable
/// Retrieves the current status of a job identified by the specified handle. /// Retrieves the current status of a job identified by the specified handle.
/// </summary> /// </summary>
/// <param name="handle">The handle representing the job whose status is to be retrieved. The handle must be valid.</param> /// <param name="handle">The handle representing the job whose status is to be retrieved. The handle must be valid.</param>
/// <returns>The current status of the job as a <see cref="JobStatus"/> value. /// <returns>The current status of the job as a <see cref="JobState"/> value.
/// Returns <see cref="JobStatus.Invalid"/> if the handle is invalid or the job does not exist.</returns> /// Returns <see cref="JobState.Invalid"/> if the handle is invalid or the job does not exist.</returns>
public JobStatus GetJobStatus(JobHandle handle) public JobState GetJobStatus(JobHandle handle)
{ {
if (!handle.IsValid) if (!handle.IsValid)
{ {
return JobStatus.Invalid; return JobState.Invalid;
} }
ref var jobInfo = ref _jobInfoPool.GetElementReferenceAt(handle._id, handle._generation, out var exist); ref var jobInfo = ref _jobInfoPool.GetElementReferenceAt(handle._id, handle._generation, out var exist);
if (!exist) if (!exist)
{ {
return JobStatus.Invalid; return JobState.Invalid;
} }
return (JobStatus)Volatile.Read(ref Unsafe.As<JobStatus, int>(ref jobInfo.status)); return (JobState)Volatile.Read(ref Unsafe.As<JobState, int>(ref jobInfo.state));
} }
/// <summary> /// <summary>
@@ -399,7 +399,7 @@ public unsafe sealed class JobScheduler : IDisposable
var spin = new SpinWait(); var spin = new SpinWait();
while (_jobInfoPool.TryGetElement(handle._id, handle._generation, out var jobInfo)) while (_jobInfoPool.TryGetElement(handle._id, handle._generation, out var jobInfo))
{ {
if (jobInfo.status == JobStatus.Completed) if (jobInfo.state == JobState.Completed)
{ {
return; return;
} }

View File

@@ -6,6 +6,7 @@
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<AllowUnsafeBlocks>True</AllowUnsafeBlocks> <AllowUnsafeBlocks>True</AllowUnsafeBlocks>
<IsPackable>false</IsPackable>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@@ -75,27 +75,14 @@ internal class WorkerThread : IDisposable
continue; continue;
} }
//var handle = JobHandle.Invalid;
//// Always try the local thread and main thread queue first.
//if (!_localQueue.TryDequeue(out handle)
// && !_scheduler.TryStealJob(-1, out handle))
//{
// var randomIndex = _random.Next(0, _scheduler.WorkerCount);
// if (_scheduler.TryStealJob(randomIndex, out var tempHandle))
// {
// handle = tempHandle;
// }
//}
//DoWork: //DoWork:
var handle = FindJob(); var handle = FindJob();
ref var jobInfo = ref _scheduler.GetJobInfoReference(handle, out var exist); ref var jobInfo = ref _scheduler.GetJobInfoReference(handle, out var exist);
if (exist) if (exist)
{ {
Interlocked.CompareExchange(ref jobInfo.status, JobStatus.Running, JobStatus.Scheduled); Interlocked.CompareExchange(ref jobInfo.state, JobState.Running, JobState.Scheduled);
var executeDelegate = jobInfo.executeDelegate; var executeDelegate = jobInfo.pExecutionFunc;
if (executeDelegate == null if (executeDelegate == null
|| executeDelegate(jobInfo.pJobData, ref jobInfo.jobRanges, ref jobInfo.remainingBatches, _index)) || executeDelegate(jobInfo.pJobData, ref jobInfo.jobRanges, ref jobInfo.remainingBatches, _index))

View File

@@ -5,6 +5,7 @@
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<AllowUnsafeBlocks>True</AllowUnsafeBlocks> <AllowUnsafeBlocks>True</AllowUnsafeBlocks>
<IsPackable>false</IsPackable>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">

View File

@@ -1,6 +1,7 @@
using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Numerics;
namespace Misaki.HighPerformance.Mathematics.CodeGen.Generators namespace Misaki.HighPerformance.Mathematics.CodeGen.Generators
{ {
@@ -332,7 +333,7 @@ namespace Misaki.HighPerformance.Mathematics.CodeGen.Generators
var asResult = $"As{typeSimpleName}()"; var asResult = $"As{typeSimpleName}()";
// Add // Add
sourceBuilder.AppendLine($@" sourceBuilder.Append($@"
{INLINE_METHOD_ATTRIBUTE} {INLINE_METHOD_ATTRIBUTE}
public static {typeName} operator +({typeName} lhs, {typeName} rhs) public static {typeName} operator +({typeName} lhs, {typeName} rhs)
{{ {{
@@ -350,7 +351,22 @@ namespace Misaki.HighPerformance.Mathematics.CodeGen.Generators
public static {typeName} operator +({componentType} lhs, {typeName} rhs) public static {typeName} operator +({componentType} lhs, {typeName} rhs)
{{ {{
return new {typeName}(lhs) + rhs; return new {typeName}(lhs) + rhs;
}}"); }}
#if NET10_0_OR_GREATER
// Use scaler here to let JIT handle the simd optimization since we can not do a in-place vectorlization manually.
{INLINE_METHOD_ATTRIBUTE}
public void operator +=({typeName} other)
{{");
for (var i = 0; i < typeInfo.Row; i++)
{
sourceBuilder.Append($@"
this.{_vectorComponents[i]} += other.{_vectorComponents[i]};");
}
sourceBuilder.AppendLine($@"
}}
#endif");
// Subtract // Subtract
sourceBuilder.AppendLine($@" sourceBuilder.AppendLine($@"
@@ -371,7 +387,22 @@ namespace Misaki.HighPerformance.Mathematics.CodeGen.Generators
public static {typeName} operator -({componentType} lhs, {typeName} rhs) public static {typeName} operator -({componentType} lhs, {typeName} rhs)
{{ {{
return new {typeName}(lhs) - rhs; return new {typeName}(lhs) - rhs;
}}"); }}
#if NET10_0_OR_GREATER
// Use scaler here to let JIT handle the simd optimization since we can not do a in-place vectorlization manually.
{INLINE_METHOD_ATTRIBUTE}
public void operator -=({typeName} other)
{{");
for (var i = 0; i < typeInfo.Row; i++)
{
sourceBuilder.Append($@"
this.{_vectorComponents[i]} -= other.{_vectorComponents[i]};");
}
sourceBuilder.AppendLine($@"
}}
#endif");
// Multiply // Multiply
sourceBuilder.AppendLine($@" sourceBuilder.AppendLine($@"
@@ -393,7 +424,22 @@ namespace Misaki.HighPerformance.Mathematics.CodeGen.Generators
public static {typeName} operator *({componentType} lhs, {typeName} rhs) public static {typeName} operator *({componentType} lhs, {typeName} rhs)
{{ {{
return new {typeName}(lhs) * rhs; return new {typeName}(lhs) * rhs;
}}"); }}
#if NET10_0_OR_GREATER
// Use scaler here to let JIT handle the simd optimization since we can not do a in-place vectorlization manually.
{INLINE_METHOD_ATTRIBUTE}
public void operator *=({typeName} other)
{{");
for (var i = 0; i < typeInfo.Row; i++)
{
sourceBuilder.Append($@"
this.{_vectorComponents[i]} *= other.{_vectorComponents[i]};");
}
sourceBuilder.AppendLine($@"
}}
#endif");
// Divide // Divide
sourceBuilder.AppendLine($@" sourceBuilder.AppendLine($@"
@@ -415,7 +461,22 @@ namespace Misaki.HighPerformance.Mathematics.CodeGen.Generators
public static {typeName} operator /({componentType} lhs, {typeName} rhs) public static {typeName} operator /({componentType} lhs, {typeName} rhs)
{{ {{
return new {typeName}(lhs) / rhs; return new {typeName}(lhs) / rhs;
}}"); }}
#if NET10_0_OR_GREATER
// Use scaler here to let JIT handle the simd optimization since we can not do a in-place vectorlization manually.
{INLINE_METHOD_ATTRIBUTE}
public void operator /=({typeName} other)
{{");
for (var i = 0; i < typeInfo.Row; i++)
{
sourceBuilder.Append($@"
this.{_vectorComponents[i]} /= other.{_vectorComponents[i]};");
}
sourceBuilder.AppendLine($@"
}}
#endif");
// Modulus // Modulus
sourceBuilder.AppendLine($@" sourceBuilder.AppendLine($@"
@@ -435,7 +496,22 @@ namespace Misaki.HighPerformance.Mathematics.CodeGen.Generators
public static {typeName} operator %({componentType} lhs, {typeName} rhs) public static {typeName} operator %({componentType} lhs, {typeName} rhs)
{{ {{
return new {typeName}(lhs) % rhs; return new {typeName}(lhs) % rhs;
}}"); }}
#if NET10_0_OR_GREATER
// Use scaler here to let JIT handle the simd optimization since we can not do a in-place vectorlization manually.
{INLINE_METHOD_ATTRIBUTE}
public void operator %=({typeName} other)
{{");
for (var i = 0; i < typeInfo.Row; i++)
{
sourceBuilder.Append($@"
this.{_vectorComponents[i]} %= other.{_vectorComponents[i]};");
}
sourceBuilder.AppendLine($@"
}}
#endif");
// Unary operators // Unary operators
sourceBuilder.AppendLine($@" sourceBuilder.AppendLine($@"
@@ -594,9 +670,18 @@ namespace Misaki.HighPerformance.Mathematics.CodeGen.Generators
{INLINE_METHOD_ATTRIBUTE} {INLINE_METHOD_ATTRIBUTE}
public static global::System.Runtime.Intrinsics.Vector{_vectorBitsSize}<{componentType}> AsVector{_vectorBitsSize}(this {typeName} value) public static global::System.Runtime.Intrinsics.Vector{_vectorBitsSize}<{componentType}> AsVector{_vectorBitsSize}(this {typeName} value)
{{"); {{");
var fullTypeName = $"{typeInfo.TypePrefix}{typeInfo.Row + _missingComponents}";
if (typeInfo.Row == 4)
{
sourceBuilder.Append($@"
return global::System.Runtime.CompilerServices.Unsafe.BitCast<{typeName}, global::System.Runtime.Intrinsics.Vector{_vectorBitsSize}<{componentType}>>(value);");
}
else
{
sourceBuilder.Append($@"
return global::System.Runtime.Intrinsics.Vector{_vectorBitsSize}.Create({string.Join(", ", Enumerable.Range(0, typeInfo.Row + _missingComponents).Select(i => i < typeInfo.Row ? $"value.{_vectorComponents[i]}" : "1"))});");
}
sourceBuilder.Append($@" sourceBuilder.Append($@"
return global::System.Runtime.Intrinsics.Vector{_vectorBitsSize}.Create({string.Join(", ", Enumerable.Range(0, typeInfo.Row + _missingComponents).Select(i => i < typeInfo.Row ? $"value.{_vectorComponents[i]}" : "1"))});
}} }}
{INLINE_METHOD_ATTRIBUTE} {INLINE_METHOD_ATTRIBUTE}

View File

@@ -5,6 +5,9 @@
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<AllowUnsafeBlocks>True</AllowUnsafeBlocks> <AllowUnsafeBlocks>True</AllowUnsafeBlocks>
<Title>$(AssemblyName)</Title>
<Authors>Misaki</Authors>
<IsPackable>false</IsPackable>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@@ -6,10 +6,10 @@ namespace Misaki.HighPerformance.Test.Benchmark;
public class MathematicsBenchmark public class MathematicsBenchmark
{ {
[Params(10, 100)] [Params(10)]
public int count = 10; public int count = 10;
[Benchmark(Baseline = true)] [Benchmark]
public void Vector2Add() public void Vector2Add()
{ {
var a = new Vector2(1, 2); var a = new Vector2(1, 2);
@@ -25,8 +25,8 @@ public class MathematicsBenchmark
[Benchmark] [Benchmark]
public void Float2Add() public void Float2Add()
{ {
var a = new float2(1); var a = new float2(1, 2);
var b = new float2(5); var b = new float2(5, 6);
var result = new float2(); var result = new float2();
for (var i = 0; i < count; i++) for (var i = 0; i < count; i++)
@@ -34,4 +34,30 @@ public class MathematicsBenchmark
result += a + b; result += a + b;
} }
} }
[Benchmark]
public void Vector4Add()
{
var a = new Vector4(1, 2, 3, 4);
var b = new Vector4(5, 6, 7, 8);
var result = new Vector4();
for (var i = 0; i < count; i++)
{
result += a + b;
}
}
[Benchmark]
public void Float4Add()
{
var a = new float4(1, 2, 3, 4);
var b = new float4(5, 6, 7, 8);
var result = new float4();
for (var i = 0; i < count; i++)
{
result += a + b;
}
}
} }

View File

@@ -2,7 +2,7 @@
<PropertyGroup> <PropertyGroup>
<OutputType>Exe</OutputType> <OutputType>Exe</OutputType>
<TargetFramework>net9.0</TargetFramework> <TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<PublishAot>True</PublishAot> <PublishAot>True</PublishAot>

View File

@@ -20,27 +20,4 @@
using Misaki.HighPerformance.Test.Benchmark; using Misaki.HighPerformance.Test.Benchmark;
//BenchmarkDotNet.Running.BenchmarkRunner.Run<ParallelNoiseBenchmark>(); BenchmarkDotNet.Running.BenchmarkRunner.Run<MathematicsBenchmark>();
var benchmark = new ParallelNoiseBenchmark();
var sw = new System.Diagnostics.Stopwatch();
benchmark.Setup();
for (var i = 0; i < 1024; i++)
{
benchmark.JobSystem();
}
sw.Start();
for (var i = 0; i < 1024; i++)
{
benchmark.JobSystem();
}
sw.Stop();
benchmark.Cleanup();
Console.WriteLine($"JobSystem: {sw.Elapsed.TotalMilliseconds / 1024.0} ms");

View File

@@ -4,6 +4,7 @@
<TargetFramework>net9.0</TargetFramework> <TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">