Beispiel #1
0
        public void Test(string directive, OmpDirectiveInfo expectedResult)
        {
            ParallelForDirectiveParser parser = new ParallelForDirectiveParser();

            OmpDirectiveInfo result = parser.Parse(directive);

            Assert.AreEqual(expectedResult.Options?.Count, result.Options?.Count);
        }
        private int GetNumberOfThreads(OmpDirectiveInfo directiveInfo)
        {
            int threadsAmountValue = OpenMPConstants.OMP_NUM_THREADS;

            if (directiveInfo?.Options != null && directiveInfo.Options.ContainsKey(OpenMPConstants.NUM_THREADS_OPTION))
            {
                threadsAmountValue = int.Parse(directiveInfo.Options[OpenMPConstants.NUM_THREADS_OPTION][0].ToString());
            }

            return(threadsAmountValue);
        }
Beispiel #3
0
        public void ParseNumThreadsTest()
        {
            string directive = "#region parallel for num_threads(5)";

            ParallelForDirectiveParser parser = new ParallelForDirectiveParser();

            OmpDirectiveInfo result = parser.Parse(directive);

            Assert.IsNotNull(result.Options);
            Assert.IsNotNull(result.Options["num_threads"]);
            Assert.AreEqual(5, int.Parse(result.Options["num_threads"][0]));
        }
Beispiel #4
0
        public void ParseThreadPrivateTest()
        {
            string directive = "#region parallel for threadprivate(a,b,c)";

            ParallelForDirectiveParser parser = new ParallelForDirectiveParser();

            OmpDirectiveInfo result = parser.Parse(directive);

            Assert.IsNotNull(result.Options);
            Assert.IsNotNull(result.Options["threadprivate"]);
            Assert.AreEqual("a", result.Options["threadprivate"][0]);
            Assert.AreEqual("b", result.Options["threadprivate"][1]);
            Assert.AreEqual("c", result.Options["threadprivate"][2]);
        }
        private string GetThreadBody(List <SyntaxNode> forLoopBody, OmpDirectiveInfo directiveInfo,
                                     DirectiveSyntaxNode node, SemanticModel model, SyntaxToken loopVariable, SyntaxToken innerIterationIndexToken)
        {
            List <SyntaxNode> nodesForReplacement = new List <SyntaxNode>();

            // in case there is a for loop inside for loop...
            var internalFor = forLoopBody
                              .FirstOrDefault(n => n.GetType() == typeof(ForStatementSyntax));

            if (internalFor != null)
            {
                nodesForReplacement.Add(internalFor);
            }
            if (!nodesForReplacement.Any())
            {
                nodesForReplacement = forLoopBody
                                      .FindAll(n =>
                                               n.GetType() == typeof(ExpressionStatementSyntax) ||
                                               n.GetType() == typeof(LocalDeclarationStatementSyntax));
            }

            string[] variables = null;
            string[] threadPrivateVariables = null;
            string[] variableTypes          = null;
            if (directiveInfo?.Options != null && directiveInfo.Options.ContainsKey(OpenMPConstants.FIRST_PRIVATE_OPTION))
            {
                variables = directiveInfo.Options[OpenMPConstants.FIRST_PRIVATE_OPTION];
                int length = variables.Count();
                threadPrivateVariables = new string[length];
                variableTypes          = new string[length];

                for (int k = 0; k < length; k++)
                {
                    SyntaxNode nodeToGetType = node.Nodes[0].DescendantNodes().FirstOrDefault(
                        i =>
                        i is IdentifierNameSyntax && i.ToString() == variables[k]);

                    var          semanticInfo = model.GetSymbolInfo(nodeToGetType);
                    ILocalSymbol symbol       = (ILocalSymbol)semanticInfo.Symbol;
                    var          symbolType   = symbol.Type.ToString();

                    variableTypes[k] = symbolType;

                    string threadPrivateVarName = GenerateVariableName();

                    threadPrivateVariables[k] = threadPrivateVarName;
                }
            }

            string threadPrivateVariablesDeclaration = string.Empty;

            if (threadPrivateVariables != null)
            {
                for (int i = 0, length = threadPrivateVariables.Length; i < length; i++)
                {
                    threadPrivateVariablesDeclaration += Environment.NewLine;
                    // currently we support only primitive types to avoid
                    // problems with complex object replication
                    if (variableTypes[i] == "int[]" || variableTypes[i] == "double[]" ||
                        variableTypes[i] == "string[]")
                    {
                        threadPrivateVariablesDeclaration +=
                            $"var {threadPrivateVariables[i]} = new " +
                            $"{variableTypes[i].Substring(0, variableTypes[i].Length - 1)}{variables[i]}.Length];{Environment.NewLine}" +
                            $"Array.Copy({variables[i]}, {threadPrivateVariables[i]}, {variables[i]}.Length);";
                    }
                    else
                    {
                        threadPrivateVariablesDeclaration +=
                            "var " +
                            threadPrivateVariables[i] +
                            " = " +
                            variables[i] +
                            ";";
                    }
                }
            }

            var threadBody = new List <SyntaxNode>();

            var oldTokens = new List <SyntaxToken>
            {
                loopVariable
            };

            var newTokens = new List <SyntaxToken>
            {
                innerIterationIndexToken
            };

            if (threadPrivateVariables != null)
            {
                for (int k = 0, length = threadPrivateVariables.Count(); k < length; k++)
                {
                    oldTokens.Add(node.Nodes[0].DescendantTokens().FirstOrDefault(t =>
                                                                                  t.Text == variables[k]));
                    newTokens.Add(SyntaxFactory.IdentifierName(threadPrivateVariables[k]).GetFirstToken());
                }
            }

            foreach (SyntaxNode n in nodesForReplacement)
            {
                var replacedNode = ReplaceTokensInSyntaxNode(n, oldTokens.ToArray(), newTokens.ToArray());

                threadBody.Add(replacedNode);
            }

            return(threadPrivateVariablesDeclaration +
                   Environment.NewLine +
                   string.Join(Environment.NewLine, threadBody.Select(n => n.ToFullString())));
        }
        /// <summary>
        /// Generates parallel for loop
        /// </summary>
        /// <param name="directiveInfo">Directive info</param>
        /// <param name="node">Syntax node that represents the for loop</param>
        /// <param name="model">Semantic model</param>
        /// <returns>Generated code</returns>
        public new string Generate(OmpDirectiveInfo directiveInfo, DirectiveSyntaxNode node, SemanticModel model = null)
        {
            StreamWriter debug = new StreamWriter(@"D:\8bit\debug_some_bug.txt");

            debug.WriteLine("New Version");

            debug.WriteLine(node.Nodes.Count);
            debug.Close();
            // get all tokens that form for loop
            IList <SyntaxToken> descendantTokens = node.Nodes[0].DescendantTokens().ToList <SyntaxToken>();

            //suppose for now that there can be only one for loop variable
            if (descendantTokens[0].ToString() == "for")
            {
                // save initial number of iterations in for loop
                SyntaxToken?initialNumberOfIterationsValue = GetNumberOfIterations(descendantTokens);

                // get loop variable
                SyntaxToken loopVariable = GetLoopVariable(descendantTokens);

                // get for loop body
                List <SyntaxNode> forLoopBody = node.Nodes.GetRange(2, node.Nodes.Count - 2);

                // TODO: in case of a mistake we probably should return the initial version of code, not an empty string
                if (initialNumberOfIterationsValue == null)
                {
                    return("");
                }

                // get max possible number of threads in a thread pool
                int threadsAmountValue = GetNumberOfThreads(directiveInfo);

                // TODO: in case of a mistake we probably should return the initial version of code, not an empty string
                if (directiveInfo == null)
                {
                    return(string.Empty);
                }

                // if there are no options specified by the user, add static scheduling by default
                if (directiveInfo.Options == null || !directiveInfo.Options.Any())
                {
                    directiveInfo.Options = new Dictionary <string, string[]>()
                    {
                        { "schedule", new string[] { "static" } }
                    };
                }

                // TODO: remove redundant check
                if (directiveInfo?.Options != null)
                {
                    // if user did not specify schedule option in directive parameters, add static scheduling by default
                    if (!directiveInfo.Options.ContainsKey(OpenMPConstants.SCHEDULE_OPTION))
                    {
                        directiveInfo.Options.Add("schedule", new string[] { "static" });
                    }
                    var options = directiveInfo.Options[OpenMPConstants.SCHEDULE_OPTION];

                    // TODO: verify that default value for chunk in static and dynamic is correct
                    // according to the standard in the following code
                    string chunkValue = options.Count() > 1
                        ? options[1]
                        : options[0] == "static" ? $"{initialNumberOfIterationsValue} / {threadsAmountValue}" : "1";

                    // generate chunk size variable name and declaration
                    string chunkName = GenerateVariableName();

                    string chunkVariableDeclaration =
                        $"var {chunkName} = {chunkValue};";

                    // generate calculation of iteration portions amount
                    string numberOfPortionsValue = $"{initialNumberOfIterationsValue} / {chunkName} + " +
                                                   $"({initialNumberOfIterationsValue} % {chunkName} > 0 ? 1 : 0)";

                    string numberOfPortionsName = GenerateVariableName();

                    string numberOfPortionsVariableDeclaration =
                        $"var {numberOfPortionsName} = {numberOfPortionsValue};";

                    // variables declarations
                    string taskListName                = GenerateTaskVariableName();
                    string threadsAmountName           = GenerateVariableName();
                    string threadsAmountIndexName      = GenerateVariableName();
                    string threadsAmountIndexInnerName = GenerateVariableName();
                    string taskVariableName            = GenerateTaskVariableName();
                    string innerIterationIndexName     = GenerateVariableName();
                    string threadPortionIndexName      = GenerateVariableName();
                    string threadPortionIndexInnerName = GenerateVariableName();

                    // the size of portion that is executed by all threads one by one
                    string bigPortionSizeName = GenerateVariableName();

                    SyntaxToken innerIterationIndexToken = SyntaxFactory.IdentifierName(innerIterationIndexName).GetFirstToken();

                    string threadsAmountDeclaration =
                        $"var {threadsAmountName} = {threadsAmountValue};";

                    string numberOfPortionsPerThreadValue = $"{numberOfPortionsName} / {threadsAmountName} + " +
                                                            $"({numberOfPortionsName} % {threadsAmountName} == 0 ? 0 : 1)";

                    string numberOfPortionsPerThreadName = GenerateVariableName();

                    string numberOfPortionsPerThreadDeclaration =
                        $"var {numberOfPortionsPerThreadName} = {numberOfPortionsPerThreadValue};";

                    string bigPortionSizeValue = $"{chunkName} * {threadsAmountName}";

                    string bigPortionSizeDeclaration = $"var {bigPortionSizeName} = {bigPortionSizeValue};";

                    /**/
                    var threadBody = GetThreadBody(forLoopBody, directiveInfo, node, model, loopVariable, innerIterationIndexToken);
                    /**/

                    string finalCode = string.Empty;

                    /*CRITICAL SECTION*/
                    CodeAnalyzer analyzer      = new CodeAnalyzer(new Factories.DirectiveParserFactory());
                    var          innerOmpNodes = analyzer.GetRegionNodes(node.Nodes[1]);

                    // for now suppose that there is only one inner openmp directive
                    if (innerOmpNodes != null && innerOmpNodes.Count > 0)
                    {
                        var innerOmpNode    = innerOmpNodes[0];
                        var directiveString = innerOmpNode.RegionDirective.ToFullString().Trim();

                        var lockObjectName = GenerateVariableName();

                        if (directiveString.Contains(OpenMPConstants.CRITICAL_DIRECTIVE))
                        {
                            finalCode += $"var {lockObjectName} = new object();";

                            threadBody = $"lock({lockObjectName}){Environment.NewLine}{{" +
                                         $"{Environment.NewLine}{threadBody}{Environment.NewLine}}}";
                        }
                    }

                    /*CRITICAL SECTION*/

                    string foreachLoopVariableName = GenerateVariableName();

                    if (options[0] == "static")
                    {
                        List <string> finalCodeList = new List <string>
                        {
                            finalCode,
                            chunkVariableDeclaration,
                            numberOfPortionsVariableDeclaration,
                            threadsAmountDeclaration,
                            numberOfPortionsPerThreadDeclaration,
                            bigPortionSizeDeclaration,
                            $"System.Threading.ThreadPool.SetMaxThreads({threadsAmountName},{threadsAmountName});",
                            $" System.Collections.Generic.List<System.Threading.Tasks.Task> {taskListName} = new  System.Collections.Generic.List<System.Threading.Tasks.Task>();",
                            $"for (var {threadsAmountIndexName} = 0; {threadsAmountIndexName} < {threadsAmountName}; {threadsAmountIndexName}++)",
                            "{",
                            $"var {threadsAmountIndexInnerName} = {threadsAmountIndexName};",
                            $"var {taskVariableName} = System.Threading.Tasks.Task.Factory.StartNew(() => {{",
                            $"for (var {threadPortionIndexName} = 0; {threadPortionIndexName} < {numberOfPortionsPerThreadName}; {threadPortionIndexName}++)",
                            "{",
                            $"var {threadPortionIndexInnerName} = {threadPortionIndexName};",
                            $"for (int {innerIterationIndexName} = {threadsAmountIndexInnerName} * {chunkName} + {threadPortionIndexInnerName} * {bigPortionSizeName}; ",
                            $"{innerIterationIndexName} < {threadsAmountIndexInnerName} * {chunkName} + {threadPortionIndexInnerName} * {bigPortionSizeName} + ",
                            $"{chunkName} && {innerIterationIndexName} < {initialNumberOfIterationsValue}; {innerIterationIndexName}++)",
                            "{",
                            threadBody,
                            "}",
                            "}",
                            "}",
                            ");",
                            $"{taskListName}.Add({taskVariableName});",
                            "}",
                            $"foreach(var {foreachLoopVariableName} in {taskListName}){{",
                            $"{foreachLoopVariableName}.Wait();",
                            "}"
                        };

                        return(string.Join(Environment.NewLine, finalCodeList));
                    }

                    if (options[0] == "dynamic")
                    {
                        string globalIterationIndexName      = GenerateVariableName();
                        string numberOfGlobalIterationsValue = $"{numberOfPortionsName} / {threadsAmountName} + " +
                                                               $"({numberOfPortionsName} % {threadsAmountName} == 0 ? 0 : 1 )";
                        string numberOfGlobalIterationsName        = GenerateVariableName();
                        string numberOfGlobalIterationsDeclaration = $"var {numberOfGlobalIterationsName} = {numberOfGlobalIterationsValue};";

                        string globalIterationIndexInnerName        = GenerateVariableName();
                        string globalIterationIndexInnerDeclaration =
                            $"var {globalIterationIndexInnerName} = {globalIterationIndexName};";

                        string threadsAmountIndexInnerDeclaration =
                            $"var {threadsAmountIndexInnerName} = {threadsAmountIndexName};";

                        List <string> finalCodeList = new List <string>
                        {
                            finalCode,
                            chunkVariableDeclaration,
                            numberOfPortionsVariableDeclaration,
                            threadsAmountDeclaration,
                            numberOfGlobalIterationsDeclaration,
                            bigPortionSizeDeclaration,
                            $"System.Threading.ThreadPool.SetMaxThreads({threadsAmountName},{threadsAmountName});",
                            $" System.Collections.Generic.List<System.Threading.Tasks.Task> {taskListName} = new  System.Collections.Generic.List<System.Threading.Task>();",
                            $"for (var {globalIterationIndexName} = 0; {globalIterationIndexName} < {numberOfGlobalIterationsName}; {globalIterationIndexName}++)",
                            "{",
                            globalIterationIndexInnerDeclaration,
                            $"for (var {threadsAmountIndexName} = 0; {threadsAmountIndexName} < {threadsAmountName}; {threadsAmountIndexName}++)",
                            "{",
                            threadsAmountIndexInnerDeclaration,
                            $"var {taskVariableName} = System.Threading.Tasks.Task.Factory.StartNew(() => ",
                            "{",
                            $"for (int {innerIterationIndexName} = {threadsAmountIndexInnerName} * {chunkName} + {globalIterationIndexInnerName} * {bigPortionSizeName}; ",
                            $"{innerIterationIndexName} < {threadsAmountIndexInnerName} * {chunkName} + {globalIterationIndexInnerName} * ",
                            $"{bigPortionSizeName} + {chunkName} && {innerIterationIndexName} < {initialNumberOfIterationsValue}; {innerIterationIndexName}++)",
                            "{",
                            threadBody,
                            "}",
                            "}",
                            ");",
                            $"{taskListName}.Add({taskVariableName});",
                            "}",
                            "}",
                            $"foreach(var {foreachLoopVariableName} in {taskListName}){{",
                            $"{foreachLoopVariableName}.Wait();",
                            "}"
                        };

                        return(string.Join(Environment.NewLine, finalCodeList));
                    }

                    if (options[0] == "guided")
                    {
                        string portionSizeName        = GenerateVariableName();
                        string portionSizeDeclaration =
                            $"var {portionSizeName} = {initialNumberOfIterationsValue} / {threadsAmountName};";

                        string numberOfLeftIterationsName        = GenerateVariableName();
                        string numberOfLeftIterationsDeclaration =
                            $"var {numberOfLeftIterationsName} = {initialNumberOfIterationsValue};";

                        string threadIndexName = GenerateVariableName();

                        string numberOfExecutedIterationsName        = GenerateVariableName();
                        string numberOfExecutedIterationsDeclaration =
                            $"var {numberOfExecutedIterationsName} = 0;";

                        string numberOfExecutedIterationsInnerName = GenerateVariableName();

                        string numberOfIterationsName  = GenerateVariableName();
                        string numberOfIterationsValue =
                            $"Math.Max({numberOfLeftIterationsName} - {portionSizeName}, " +
                            $"{threadsAmountName} * {chunkName})";

                        List <string> finalCodeList = new List <string>
                        {
                            finalCode,
                            chunkVariableDeclaration,
                            threadsAmountDeclaration,
                            portionSizeDeclaration,
                            numberOfLeftIterationsDeclaration,
                            numberOfExecutedIterationsDeclaration,
                            $"System.Threading.ThreadPool.SetMaxThreads({threadsAmountName},{threadsAmountName});",
                            $" System.Collections.Generic.List<System.Threading.Tasks.Task> {taskListName} = new  System.Collections.Generic.List<System.Threading.Tasks.Task>();",
                            $"while({numberOfLeftIterationsName} > 0)",
                            "{",
                            $"for(int {threadIndexName} = 0; {threadIndexName} < {threadsAmountName} && {numberOfLeftIterationsName} > 0;",
                            $" {threadIndexName}++)",
                            "{",
                            $"int {numberOfIterationsName};",
                            $"if({portionSizeName} >= {numberOfLeftIterationsName})",
                            "{",
                            $"{numberOfIterationsName} = {numberOfLeftIterationsName};",
                            "}",
                            $"else",
                            "{",
                            $"{numberOfIterationsName} = {numberOfIterationsValue};",
                            "}",
                            $"{numberOfLeftIterationsName} -= {numberOfIterationsName};",
                            $"var {numberOfExecutedIterationsInnerName} = {numberOfExecutedIterationsName};",
                            $"var {taskVariableName} = System.Threading.Tasks.Task.Factory.StartNew(() => ",
                            "{",
                            $"for (int {innerIterationIndexName} = {numberOfExecutedIterationsInnerName}; ",
                            $"{innerIterationIndexName} < {numberOfExecutedIterationsInnerName} + {numberOfIterationsName}; {innerIterationIndexName}++)",
                            "{",
                            threadBody,
                            "}",
                            "});",
                            $"{taskListName}.Add({taskVariableName});",
                            $"{numberOfExecutedIterationsName} += {numberOfIterationsName};",
                            "}",
                            "}",
                            $"foreach(var {foreachLoopVariableName} in {taskListName}){{",
                            $"{foreachLoopVariableName}.Wait();",
                            "}"
                        };

                        return(string.Join(Environment.NewLine, finalCodeList));
                    }
                }
            }

            return("");
        }
Beispiel #7
0
 public new string Generate(OmpDirectiveInfo directiveInfo, DirectiveSyntaxNode node, SemanticModel model = null)
 {
     throw new NotImplementedException();
 }
Beispiel #8
0
        /// <summary>
        /// Method for code generation
        /// </summary>
        /// <param name="directiveInfo">Directive info</param>
        /// <param name="node">Syntax node to process</param>
        /// <param name="model">Semantic model</param>
        /// <returns>Generated code</returns>
        public string Generate(OmpDirectiveInfo directiveInfo, DirectiveSyntaxNode node, SemanticModel model = null)
        {
            var generator = _codeGeneratorFactory.GetCodeGenerator(directiveInfo.Type);

            return(generator.Generate(directiveInfo, node, model));
        }