0

I have this simple function that is used to generate neuron connections position:

using System.Collections.Generic;
using System.Drawing;

public static List<Point> GetConnectionsConnectedPosition(int connectedLayerI, int startingConnectedNeuronIndex, int outputLength)
{
    var connections = new List<Point>();
    for (int i = 0; i < outputLength; i++)
    {
        connections.Add(new Point(connectedLayerI, startingConnectedNeuronIndex + i));
    }
    return connections;
}

And now I want to create all the connections positions for a specific neuron connections using this constructor code:

using System.Drawing;
using System.Threading;
using System.Threading.Tasks;

internal NeuronConnectionsInfo(int layerIndex, int previousLayerLength, double minWeight, double maxWeight, double valueClosestTo0)
{
    Weights = new List<double>();
    ConnectedNeuronsPos = new List<Point>();

    int connectionsPerTask = 750;

    // specify task job
    int taskCount = previousLayerLength / connectionsPerTask;
    int leftConnectionCount = previousLayerLength % connectionsPerTask;

    // Initialize tasks
    List<Task<List<double>>> weigthsTasks = new List<Task<List<double>>>();
    List<Task<List<Point>>> positionsTasks = new List<Task<List<Point>>>();

    for (int i = 0; i < taskCount; i++)
    {
        weightsTasks.Add(Task.Run(() => GenerateWeigths(connectionsPerTask, minWeigth, maxWeight, valueClosestTo0));
        positionsTasks.Add(Task.Run(() => GetConnectionsConnectedTo(layerIndex - 1, connectionsPerTask * i, connectionsPerTask);
    }
    weightsTasks.Add(Task.Run(() => GenerateWeights(connectionsPerTask, minWeight, maxWeight, valueClosestTo0));  
    positionsTasks.Add(Task.Run(() => GetConnectionsConnectedTo(layerIndex - 1, connectionsPerTask * taskCount, leftConnectionsCount)); 
     
    //wait for tasks to finish
    bool isFinished = false;
    while (!isFinished)
    {
        isFinished = true;
        Thread.Sleep(20);
        foreach (weightsTask in weightsTasks)
        {
            isFinished = isFinished && weightTask.IsCompleted;
        }
        if (isFinished)
            foreach (positionTask in positionsTasks)
            {
                isFinished = isFinished && positionTask.isCompleted;
            }
    }

    for (int i = 0; i < weightsTasks; i++)
    {
        Weights.AddRange(weightsTasks[i].Result);
        ConnectedNeuronsPos.AddRange(positionsTasks[i].Result);
    }
}

Weights are being generated alright, but the problem begins with positions' X (connectedLayerI) starting at connectionsPerTask * taskCount, basically position's X starting where the last task X position should start even though y (connectedNeuronI) is being generated ok and Task's result length is also being generated alright.

While debugging I noticed that if I executed the instructions at a human speed the result was alright, then, I tried adding Thread.Sleep(20); before and after calling Task.Run(() => GetConnectionsConnectedTo(...));

This seems to solve the issue but I'm not confident that it'll solve the issue with all processors because it seems to be an error with C#'s static programming.

All answers will be accepted so don't have any hesitation on answering with your opinion or with a more optimized or secure method. Thanks in advance.

Theodor Zoulias
  • 34,835
  • 7
  • 69
  • 104
  • 2
    The lambda expressions in the Task.Run parameters will use the value of `i` at the point in time when they are executed which if very probably not what you desire. Assign the value of `i` to a variable local to the loop body and use it instead. See e.g. https://stackoverflow.com/questions/44496018/how-is-a-c-sharp-lambda-capturing-variables – Klaus Gütter Sep 30 '22 at 11:22
  • Thank you Klaus, someone can suggest a title so other people have it easier to search this question?? – Germán Gasset Sep 30 '22 at 11:43
  • Your code starts all the parallel operations at once, and the degree of parallelism is limited only by the `ThreadPool` availability, that increases over time. For a better control of the degree of parallelism you could look at this question: [How to parallelize multiple heterogeneous jobs with a specific degree of parallelism](https://stackoverflow.com/questions/60893389/how-to-parallelize-multiple-heterogeneous-jobs-with-a-specific-degree-of-paralle). – Theodor Zoulias Sep 30 '22 at 11:52
  • Finally found the duplicate: [Using the iterator variable of foreach loop in a lambda expression - why fails?](https://stackoverflow.com/questions/3168375/using-the-iterator-variable-of-foreach-loop-in-a-lambda-expression-why-fails) – Klaus Gütter Sep 30 '22 at 11:55
  • As a side-note, the lengthy `while (!isFinished)` loop in your code could probably be replaced with `Task.WaitAll(weightsTasks.Cast().Concat(positionsTasks).ToArray());`. – Theodor Zoulias Sep 30 '22 at 11:58
  • 1
    Another possible duplicate: [Captured variable in a loop in C#](https://stackoverflow.com/questions/271440/captured-variable-in-a-loop-in-c-sharp). – Theodor Zoulias Sep 30 '22 at 12:00

0 Answers0