optimize para performance of buffered stack
This commit is contained in:
+117
-3
@@ -2,8 +2,8 @@
|
||||
// -----------------------------------------------------------------------
|
||||
// file="Program"
|
||||
// Project: StgSharp
|
||||
// AuthorGroup: Nitload Space
|
||||
// Copyright (c) Nitload Space. All rights reserved.
|
||||
// AuthorGroup: Nitload
|
||||
// Copyright (c) Nitload. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -40,10 +40,12 @@ using StgSharp.Script;
|
||||
using StgSharp.Script.Express;
|
||||
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.Intrinsics;
|
||||
using System.Runtime.Intrinsics.X86;
|
||||
using System.Threading;
|
||||
using System.Xml.XPath;
|
||||
|
||||
namespace StgSharp
|
||||
@@ -51,7 +53,7 @@ namespace StgSharp
|
||||
internal static partial class Program
|
||||
{
|
||||
|
||||
private static string testExpPath = @"D:\Programmer\stepcode\data\ap203\ap203.exp";
|
||||
private static string testExpPath = @"D:\\Programmer\\stepcode\\data\\ap203\\ap203.exp";
|
||||
|
||||
internal static unsafe void Main(string[] args)
|
||||
{
|
||||
@@ -59,6 +61,118 @@ namespace StgSharp
|
||||
{
|
||||
World.Init();
|
||||
|
||||
// New test with synchronized start:
|
||||
// - 8 producer threads, each pushing 1000 unique integers
|
||||
// - 8 consumer threads, each attempting to pop 1000 times
|
||||
// - Consumers print one line per successful pop
|
||||
// - Finally, print popped/remaining counts and values
|
||||
|
||||
const int producerThreads = 8;
|
||||
const int consumerThreads = 8;
|
||||
const int perProducer = 1000;
|
||||
const int perConsumerAttempts = 1000;
|
||||
|
||||
ConcurrentBufferStack<int> stack = new ConcurrentBufferStack<int>();
|
||||
Thread[] producers = new Thread[producerThreads];
|
||||
Thread[] consumers = new Thread[consumerThreads];
|
||||
ConcurrentBag<int> popped = new ConcurrentBag<int>();
|
||||
|
||||
int totalThreads = producerThreads + consumerThreads;
|
||||
using CountdownEvent ready = new CountdownEvent(totalThreads);
|
||||
using ManualResetEventSlim startGate = new ManualResetEventSlim(false);
|
||||
|
||||
for (int c = 0; c < consumerThreads; c++)
|
||||
{
|
||||
consumers[c] = new Thread(() => {
|
||||
ready.Signal();
|
||||
startGate.Wait();
|
||||
|
||||
for (int k = 0; k < perConsumerAttempts; k++)
|
||||
{
|
||||
if (stack.TryPop(out int v))
|
||||
{
|
||||
popped.Add(v);
|
||||
Console.WriteLine($"pop: {v}");
|
||||
} else
|
||||
{
|
||||
Thread.Yield();
|
||||
}
|
||||
}
|
||||
})
|
||||
{
|
||||
IsBackground = true
|
||||
};
|
||||
}
|
||||
|
||||
for (int p = 0; p < producerThreads; p++)
|
||||
{
|
||||
int captured = p;
|
||||
producers[p] = new Thread(() => {
|
||||
ready.Signal();
|
||||
startGate.Wait();
|
||||
|
||||
int begin = captured * perProducer;
|
||||
for (int j = 0; j < perProducer; j++)
|
||||
{
|
||||
stack.Push(begin + j);
|
||||
if ((j & 0xFF) == 0) {
|
||||
Thread.Yield();
|
||||
}
|
||||
}
|
||||
})
|
||||
{
|
||||
IsBackground = true
|
||||
};
|
||||
}
|
||||
|
||||
foreach (Thread t in consumers) {
|
||||
t.Start();
|
||||
}
|
||||
|
||||
foreach (Thread t in producers) {
|
||||
t.Start();
|
||||
}
|
||||
|
||||
// Ensure all threads are ready, then start simultaneously
|
||||
ready.Wait();
|
||||
startGate.Set();
|
||||
|
||||
foreach (Thread t in producers) {
|
||||
t.Join();
|
||||
}
|
||||
|
||||
foreach (Thread t in consumers) {
|
||||
t.Join();
|
||||
}
|
||||
|
||||
// Gather remaining data
|
||||
List<int> remaining = new System.Collections.Generic.List<int>();
|
||||
while (stack.TryPop(out int value)) {
|
||||
remaining.Add(value);
|
||||
}
|
||||
|
||||
Console.WriteLine($"Popped count: {popped.Count}");
|
||||
Console.WriteLine("Popped values:");
|
||||
foreach (int v in popped)
|
||||
{
|
||||
Console.Write(v);
|
||||
Console.Write('\t');
|
||||
}
|
||||
Console.WriteLine();
|
||||
|
||||
Console.WriteLine($"Remaining count: {remaining.Count}");
|
||||
Console.WriteLine("Remaining values:");
|
||||
foreach (int v in remaining)
|
||||
{
|
||||
Console.Write(v);
|
||||
Console.Write('\t');
|
||||
}
|
||||
Console.WriteLine();
|
||||
|
||||
// Sanity check
|
||||
Console.WriteLine($"Produced: {producerThreads * perProducer}, Popped+Remaining: {popped.Count + remaining.Count}");
|
||||
|
||||
/*
|
||||
// TestMatrixParallel();
|
||||
|
||||
// 原有的矩阵测试代码
|
||||
|
||||
Reference in New Issue
Block a user