Initial project import
This commit is contained in:
commit
23f2d29e32
11957 files changed
+1754577
No files matched your search
@@ -0,0 +1,105 @@
|
||||
# Comparing C# and V Boids Algorithm Implementations
|
||||
|
||||
## Running the C# program:
|
||||
|
||||
```
|
||||
dotnet run
|
||||
```
|
||||
|
||||
Creating a release version of the C# program:
|
||||
|
||||
```
|
||||
dotnet publish -c Release -r ubuntu.20.04-x64
|
||||
```
|
||||
|
||||
The generated executable will be in
|
||||
`/v/vnew/bench/vectors/bin/Release/net7.0/ubuntu.20.04-x64/publish/vectors`
|
||||
Its size is ~64MB . After stripping, the executable shrinks to just 11MB,
|
||||
but unfortunately it also stops running after stripping :-| .
|
||||
|
||||
## Compiling and running the V program:
|
||||
|
||||
```
|
||||
v crun vectors.v
|
||||
```
|
||||
|
||||
... produces and runs a `vectors` executable which is ~1.3MB in size.
|
||||
|
||||
Compiling and running the V program, compiled with -prod:
|
||||
|
||||
```
|
||||
v -prod crun vectors.v
|
||||
```
|
||||
|
||||
... produces and runs a `vectors` executable which is ~176KB in size.
|
||||
After stripping, the executable shrinks to 157KB. It can still run after
|
||||
stripping.
|
||||
|
||||
Note: using `crun` will make sure that the compilation will happen just
|
||||
once at the start, and then the executable will be just reused by the
|
||||
subsequent commands with identical options. It will also ensure that
|
||||
the compiled executable will not be removed, unlike `run` .
|
||||
|
||||
## Some measurements and comparisons
|
||||
|
||||
Note: the following was done on Intel(R) Core(TM) i3-3225, 16GB RAM:
|
||||
|
||||
```
|
||||
#0 13:41:35 ᛋ master /v/vnew/bench/vectors❱rm -rf vectors
|
||||
#0 13:41:49 ᛋ master /v/vnew/bench/vectors❱
|
||||
#0 13:41:49 ᛋ master /v/vnew/bench/vectors❱v -o vectors_development vectors.v
|
||||
#0 13:42:14 ᛋ master /v/vnew/bench/vectors❱v -o vectors_production -prod vectors.v
|
||||
#0 13:42:28 ᛋ master /v/vnew/bench/vectors❱
|
||||
#0 13:42:29 ᛋ master /v/vnew/bench/vectors❱hyperfine ./bin/Release/net7.0/ubuntu.20.04-x64/publish/vectors ./vectors_development ./vectors_production
|
||||
Benchmark 1: ./bin/Release/net7.0/ubuntu.20.04-x64/publish/vectors
|
||||
Time (mean ± σ): 347.4 ms ± 7.4 ms [User: 334.4 ms, System: 13.0 ms]
|
||||
Range (min … max): 340.2 ms … 361.7 ms 10 runs
|
||||
|
||||
Benchmark 2: ./vectors_development
|
||||
Time (mean ± σ): 882.6 ms ± 14.0 ms [User: 880.3 ms, System: 2.3 ms]
|
||||
Range (min … max): 862.4 ms … 912.9 ms 10 runs
|
||||
|
||||
Benchmark 3: ./vectors_production
|
||||
Time (mean ± σ): 217.9 ms ± 9.4 ms [User: 216.8 ms, System: 0.9 ms]
|
||||
Range (min … max): 206.4 ms … 241.3 ms 12 runs
|
||||
|
||||
Summary
|
||||
./vectors_production ran
|
||||
1.59 ± 0.08 times faster than ./bin/Release/net7.0/ubuntu.20.04-x64/publish/vectors
|
||||
4.05 ± 0.19 times faster than ./vectors_development
|
||||
#0 13:43:00 ᛋ master /v/vnew/bench/vectors❱
|
||||
#0 13:45:07 ᛋ master /v/vnew/bench/vectors❱ls -nlarS ./bin/Release/net7.0/ubuntu.20.04-x64/publish/vectors ./vectors_development ./vectors_production
|
||||
-rwxrwxr-x 1 1000 1000 179384 Sep 6 13:42 ./vectors_production
|
||||
-rwxrwxr-x 1 1000 1000 1320764 Sep 6 13:42 ./vectors_development
|
||||
-rwxr-xr-x 1 1000 1000 66732821 Sep 6 13:40 ./bin/Release/net7.0/ubuntu.20.04-x64/publish/vectors
|
||||
#0 13:45:12 ᛋ master /v/vnew/bench/vectors❱
|
||||
#0 13:53:12 ᛋ master /v/vnew/bench/vectors❱alias xtime='/usr/bin/time -f "CPU: %Us\tReal: %es\tElapsed: %E\tRAM: %MKB\t%C"'
|
||||
#0 13:53:42 ᛋ master /v/vnew/bench/vectors❱xtime ./vectors_development
|
||||
5.0498380931718074e+07 - 5.0504723697762154e+07 - 5.040198063489048e+07
|
||||
0.0 - 0.0 - 0.0
|
||||
CPU: 0.87s Real: 0.87s Elapsed: 0:00.87 RAM: 4404KB ./vectors_development
|
||||
#0 13:53:52 ᛋ master /v/vnew/bench/vectors❱xtime ./vectors_production
|
||||
4.971971434731853e+07 - 4.973120986372047e+07 - 5.030988639116867e+07
|
||||
0.0 - 0.0 - 0.0
|
||||
CPU: 0.20s Real: 0.20s Elapsed: 0:00.20 RAM: 3228KB ./vectors_production
|
||||
#0 13:53:58 ᛋ master /v/vnew/bench/vectors❱xtime ./bin/Release/net7.0/ubuntu.20.04-x64/publish/vectors
|
||||
(49627678.97075553, 50302418.6269631, 49705582.70645027)
|
||||
(0, 0, 0)
|
||||
CPU: 0.33s Real: 0.34s Elapsed: 0:00.34 RAM: 30544KB ./bin/Release/net7.0/ubuntu.20.04-x64/publish/vectors
|
||||
#0 13:54:02 ᛋ master /v/vnew/bench/vectors❱
|
||||
#0 14:01:33 ᛋ master /v/vnew/bench/vectors❱
|
||||
#0 14:01:35 ᛋ master /v/vnew/bench/vectors❱xtime v vectors.v
|
||||
CPU: 0.41s Real: 0.36s Elapsed: 0:00.36 RAM: 59412KB v vectors.v
|
||||
#0 14:01:41 ᛋ master /v/vnew/bench/vectors❱
|
||||
#0 14:01:42 ᛋ master /v/vnew/bench/vectors❱xtime v -prod vectors.v
|
||||
CPU: 4.97s Real: 5.11s Elapsed: 0:05.11 RAM: 80732KB v -prod vectors.v
|
||||
#0 14:01:48 ᛋ master /v/vnew/bench/vectors❱
|
||||
#0 14:01:50 ᛋ master /v/vnew/bench/vectors❱xtime dotnet publish -c Release -r ubuntu.20.04-x64
|
||||
MSBuild version 17.7.1+971bf70db for .NET
|
||||
Determining projects to restore...
|
||||
All projects are up-to-date for restore.
|
||||
vectors -> /v/vnew/bench/vectors/bin/Release/net7.0/ubuntu.20.04-x64/vectors.dll
|
||||
vectors -> /v/vnew/bench/vectors/bin/Release/net7.0/ubuntu.20.04-x64/publish/
|
||||
CPU: 2.34s Real: 2.64s Elapsed: 0:02.64 RAM: 159816KB dotnet publish -c Release -r ubuntu.20.04-x64
|
||||
#0 14:01:56 ᛋ master /v/vnew/bench/vectors❱
|
||||
```
|
||||
@@ -0,0 +1,193 @@
|
||||
using System;
|
||||
|
||||
internal readonly struct Vector
|
||||
{
|
||||
public readonly double X;
|
||||
public readonly double Y;
|
||||
public readonly double Z;
|
||||
|
||||
public Vector(double x, double y, double z)
|
||||
{
|
||||
X = x;
|
||||
Y = y;
|
||||
Z = z;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"({X}, {Y}, {Z})";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class Program
|
||||
{
|
||||
static void Main(string[] args)
|
||||
{
|
||||
const int boidsCount = 10000;
|
||||
|
||||
var positions = new Vector[boidsCount];
|
||||
var velocities = new Vector[boidsCount];
|
||||
|
||||
const double maxCoordinate = 10000.0;
|
||||
|
||||
var random = new Random();
|
||||
|
||||
for (var positionIndex = 0; positionIndex < positions.Length; positionIndex++)
|
||||
{
|
||||
positions[positionIndex] = new Vector(
|
||||
x: random.NextDouble() * maxCoordinate,
|
||||
y: random.NextDouble() * maxCoordinate,
|
||||
z: random.NextDouble() * maxCoordinate
|
||||
);
|
||||
}
|
||||
|
||||
const double cohesionDistance = 10.0;
|
||||
const double separationDistance = 5.0;
|
||||
|
||||
var closeBoids = new List<int>();
|
||||
|
||||
for (var boidIndex = 0; boidIndex < positions.Length; boidIndex++)
|
||||
{
|
||||
var position = positions[boidIndex];
|
||||
closeBoids.Clear();
|
||||
|
||||
for (var otherBoidIndex = 0; otherBoidIndex < positions.Length; otherBoidIndex++)
|
||||
{
|
||||
if (boidIndex == otherBoidIndex)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var otherPosition = positions[otherBoidIndex];
|
||||
|
||||
var differenceX = position.X - otherPosition.X;
|
||||
var differenceY = position.Y - otherPosition.Y;
|
||||
var differenceZ = position.Z - otherPosition.Z;
|
||||
|
||||
var distance = differenceX * differenceX +
|
||||
differenceY * differenceY +
|
||||
differenceZ * differenceZ;
|
||||
|
||||
if (distance <= cohesionDistance * cohesionDistance)
|
||||
{
|
||||
closeBoids.Add(otherBoidIndex);
|
||||
}
|
||||
}
|
||||
|
||||
if (closeBoids.Count == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var cohesion = new Vector(0.0, 0.0, 0.0);
|
||||
var separation = new Vector(0.0, 0.0, 0.0);
|
||||
var separationCount = 0;
|
||||
var alignment = new Vector(0.0, 0.0, 0.0);
|
||||
|
||||
foreach (var closeBoidIndex in closeBoids)
|
||||
{
|
||||
var closeBoidPosition = positions[closeBoidIndex];
|
||||
|
||||
cohesion = new Vector(
|
||||
cohesion.X + closeBoidPosition.X,
|
||||
cohesion.Y + closeBoidPosition.Y,
|
||||
cohesion.Z + closeBoidPosition.Z
|
||||
);
|
||||
|
||||
var differenceFromClosest = new Vector(
|
||||
position.X - closeBoidPosition.X,
|
||||
position.Y - closeBoidPosition.Y,
|
||||
position.Z - closeBoidPosition.Z
|
||||
);
|
||||
|
||||
var differenceMagnitude = Math.Sqrt(differenceFromClosest.X * differenceFromClosest.X + differenceFromClosest.Y * differenceFromClosest.Y + differenceFromClosest.Z * differenceFromClosest.Z);
|
||||
|
||||
if (differenceMagnitude <= separationDistance)
|
||||
{
|
||||
separation = new Vector(
|
||||
separation.X + differenceFromClosest.X / differenceMagnitude,
|
||||
separation.Y + differenceFromClosest.Y / differenceMagnitude,
|
||||
separation.Z + differenceFromClosest.Z / differenceMagnitude
|
||||
);
|
||||
|
||||
separationCount++;
|
||||
}
|
||||
|
||||
var closeBoidVelocity = velocities[closeBoidIndex];
|
||||
|
||||
alignment = new Vector(
|
||||
alignment.X + closeBoidVelocity.X,
|
||||
alignment.Y + closeBoidVelocity.Y,
|
||||
alignment.Z + closeBoidVelocity.Z
|
||||
);
|
||||
}
|
||||
|
||||
cohesion = new Vector(
|
||||
cohesion.X / closeBoids.Count,
|
||||
cohesion.Y / closeBoids.Count,
|
||||
cohesion.Z / closeBoids.Count
|
||||
);
|
||||
|
||||
var cohesionForce = new Vector(
|
||||
cohesion.X - position.X,
|
||||
cohesion.Y - position.Y,
|
||||
cohesion.Z - position.Z
|
||||
);
|
||||
|
||||
if (separationCount > 0)
|
||||
{
|
||||
separation = new Vector(
|
||||
separation.X / separationCount,
|
||||
separation.Y / separationCount,
|
||||
separation.Z / separationCount
|
||||
);
|
||||
}
|
||||
|
||||
alignment = new Vector(
|
||||
alignment.X / closeBoids.Count,
|
||||
alignment.Y / closeBoids.Count,
|
||||
alignment.Z / closeBoids.Count
|
||||
);
|
||||
|
||||
var currentVelocity = velocities[boidIndex];
|
||||
|
||||
velocities[boidIndex] = new Vector(
|
||||
currentVelocity.X + cohesionForce.X + separation.X + alignment.X,
|
||||
currentVelocity.Y + cohesionForce.Y + separation.Y + alignment.Y,
|
||||
currentVelocity.Z + cohesionForce.Z + separation.Z + alignment.Z
|
||||
);
|
||||
}
|
||||
|
||||
var positionSum = new Vector(0.0, 0.0, 0.0);
|
||||
var velocitySum = new Vector(0.0, 0.0, 0.0);
|
||||
|
||||
for (var boidIndex = 0; boidIndex < positions.Length; boidIndex++)
|
||||
{
|
||||
var position = positions[boidIndex];
|
||||
var velocity = velocities[boidIndex];
|
||||
|
||||
positions[boidIndex] = new Vector(
|
||||
position.X + velocity.X,
|
||||
position.Y + velocity.Y,
|
||||
position.Z + velocity.Z
|
||||
);
|
||||
|
||||
positionSum = new Vector(
|
||||
positionSum.X + position.X,
|
||||
positionSum.Y + position.Y,
|
||||
positionSum.Z + position.Z
|
||||
);
|
||||
|
||||
velocitySum = new Vector(
|
||||
velocitySum.X + velocity.X,
|
||||
velocitySum.Y + velocity.Y,
|
||||
velocitySum.Z + velocity.Z
|
||||
);
|
||||
}
|
||||
|
||||
Console.WriteLine(positionSum.ToString());
|
||||
Console.WriteLine(velocitySum.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<PublishSingleFile>true</PublishSingleFile>
|
||||
<SelfContained>true</SelfContained>
|
||||
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<OutputType>Exe</OutputType>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1 @@
|
||||
{"runtimeOptions":{"framework":{"name":"Microsoft.NETCore.App","version":"7.0.10"}}}
|
||||
@@ -0,0 +1,164 @@
|
||||
module main
|
||||
|
||||
import rand
|
||||
import math
|
||||
|
||||
struct Vector {
|
||||
x f64
|
||||
y f64
|
||||
z f64
|
||||
}
|
||||
|
||||
const boids_count = 10000
|
||||
const max_coordinate = 10000.0
|
||||
const cohesion_distance = 10.0
|
||||
const separation_distance = 5.0
|
||||
|
||||
@[direct_array_access]
|
||||
fn main() {
|
||||
mut positions := [boids_count]Vector{}
|
||||
mut velocities := [boids_count]Vector{}
|
||||
|
||||
for position_index in 0 .. positions.len {
|
||||
positions[position_index] = Vector{
|
||||
x: rand.f64() * max_coordinate
|
||||
y: rand.f64() * max_coordinate
|
||||
z: rand.f64() * max_coordinate
|
||||
}
|
||||
}
|
||||
|
||||
for boid_index in 0 .. positions.len {
|
||||
position := positions[boid_index]
|
||||
mut close_boids_ids := []int{}
|
||||
|
||||
for other_boid_index in 0 .. positions.len {
|
||||
if boid_index == other_boid_index {
|
||||
continue
|
||||
}
|
||||
|
||||
other_position := positions[other_boid_index]
|
||||
|
||||
difference_x := position.x - other_position.x
|
||||
difference_y := position.y - other_position.y
|
||||
difference_z := position.z - other_position.z
|
||||
|
||||
distance := difference_x * difference_x + difference_y * difference_y +
|
||||
difference_z * difference_z
|
||||
|
||||
if distance <= cohesion_distance * cohesion_distance {
|
||||
close_boids_ids << other_boid_index
|
||||
}
|
||||
}
|
||||
|
||||
if close_boids_ids.len == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
mut cohesion := Vector{}
|
||||
mut separation := Vector{}
|
||||
mut separation_count := 0
|
||||
mut alignment := Vector{}
|
||||
|
||||
for close_boid_id in close_boids_ids {
|
||||
close_boid_position := positions[close_boid_id]
|
||||
|
||||
cohesion = Vector{
|
||||
x: cohesion.x + close_boid_position.x
|
||||
y: cohesion.y + close_boid_position.y
|
||||
z: cohesion.z + close_boid_position.z
|
||||
}
|
||||
|
||||
difference_from_closest := Vector{
|
||||
x: position.x - close_boid_position.x
|
||||
y: position.y - close_boid_position.y
|
||||
z: position.z - close_boid_position.z
|
||||
}
|
||||
|
||||
difference_magnitude := math.sqrt(
|
||||
difference_from_closest.x * difference_from_closest.x +
|
||||
difference_from_closest.y * difference_from_closest.y +
|
||||
difference_from_closest.z * difference_from_closest.z)
|
||||
|
||||
if difference_magnitude <= separation_distance {
|
||||
separation = Vector{
|
||||
x: separation.x + difference_from_closest.x / difference_magnitude
|
||||
y: separation.y + difference_from_closest.y / difference_magnitude
|
||||
z: separation.z + difference_from_closest.z / difference_magnitude
|
||||
}
|
||||
|
||||
separation_count += 1
|
||||
}
|
||||
|
||||
close_boid_velocity := velocities[close_boid_id]
|
||||
|
||||
alignment = Vector{
|
||||
x: alignment.x + close_boid_velocity.x
|
||||
y: alignment.y + close_boid_velocity.y
|
||||
z: alignment.z + close_boid_velocity.z
|
||||
}
|
||||
}
|
||||
|
||||
cohesion = Vector{
|
||||
x: cohesion.x / close_boids_ids.len
|
||||
y: cohesion.y / close_boids_ids.len
|
||||
z: cohesion.z / close_boids_ids.len
|
||||
}
|
||||
|
||||
cohesion_force := Vector{
|
||||
x: cohesion.x - position.x
|
||||
y: cohesion.y - position.y
|
||||
z: cohesion.z - position.z
|
||||
}
|
||||
|
||||
if separation_count > 0 {
|
||||
separation = Vector{
|
||||
x: separation.x / separation_count
|
||||
y: separation.y / separation_count
|
||||
z: separation.z / separation_count
|
||||
}
|
||||
}
|
||||
|
||||
alignment = Vector{
|
||||
x: alignment.x / close_boids_ids.len
|
||||
y: alignment.y / close_boids_ids.len
|
||||
z: alignment.z / close_boids_ids.len
|
||||
}
|
||||
|
||||
current_velocity := velocities[boid_index]
|
||||
|
||||
velocities[boid_index] = Vector{
|
||||
x: current_velocity.x + cohesion_force.x + separation.x + alignment.x
|
||||
y: current_velocity.y + cohesion_force.y + separation.y + alignment.y
|
||||
z: current_velocity.z + cohesion_force.z + separation.z + alignment.z
|
||||
}
|
||||
}
|
||||
|
||||
mut position_sum := Vector{}
|
||||
mut velocity_sum := Vector{}
|
||||
|
||||
for boid_index in 0 .. positions.len {
|
||||
position := positions[boid_index]
|
||||
velocity := velocities[boid_index]
|
||||
|
||||
positions[boid_index] = Vector{
|
||||
x: position.x + velocity.x
|
||||
y: position.y + velocity.y
|
||||
z: position.z + velocity.z
|
||||
}
|
||||
|
||||
position_sum = Vector{
|
||||
x: position_sum.x + position.x
|
||||
y: position_sum.y + position.y
|
||||
z: position_sum.z + position.z
|
||||
}
|
||||
|
||||
velocity_sum = Vector{
|
||||
x: velocity_sum.x + velocity.x
|
||||
y: velocity_sum.y + velocity.y
|
||||
z: velocity_sum.z + velocity.z
|
||||
}
|
||||
}
|
||||
|
||||
println('${position_sum.x} - ${position_sum.y} - ${position_sum.z}')
|
||||
println('${velocity_sum.x} - ${velocity_sum.y} - ${velocity_sum.z}')
|
||||
}
|
||||
Reference in new issue
Block a user