Modules on the dotnet platform are .NET Core assemblies that export one or more implementations of different instantiations of the generic ITest<TInput, TOutput>
interface. The interface is defined in the DotnetRunner
assembly, and the exporting is done using MEF.
-
Create a new .NET Core class library project
/src/dotnet/modules/YourModule/YourModule.XXproj
. The extension of the project file name depends on the chosen language. Any language that can be compiled into a .NET Core class library can be used. This file structure is expected by the global runner. -
In your project add a reference to
DotnetRunner
:<ItemGroup> <ProjectReference Include="..\..\runner\DotnetRunner.csproj" /> </ItemGroup>
-
Create
/src/dotnet/modules/YourModule/CMakeLists.txt
with the following content whereYourModule
is the name of your module:project("ADBench_YourModule") add_custom_target(YourModule ALL COMMAND "dotnet" "publish" "--configuration" "${AD_BUILD_TYPE}" "--output" "${CMAKE_CURRENT_BINARY_DIR}" "-p:IntermediateOutputPath=${CMAKE_CURRENT_BINARY_DIR}/obj/" "${CMAKE_CURRENT_LIST_DIR}/YourModule.XXproj" )
-
Add the following line to
/src/dotnet/modules/CMakeLists.txt
:add_subdirectory ("YourModule")
These two steps ensure that build environment generated by cmake will build your module as well.
-
For each objective create a class implementing the interface
ITest<TInput, TOutput>
whereT
is an objective type (GMM
,BA
etc.). You can find this interface in/src/dotnet/runner/ITest.cs
.TInput
andTOutput
are input and output types specific for the objective there. They are defined in corresponding/src/dotnet/runner/Data/TData.cs
files.The functions you need to implement:
-
void Prepare(TInput input)
Converts the input data from the
TInput
type in which it is provided by the calling benchmark runner into the format optimized for use with the tested AD framework. Stores it.Optionally, performs other preparatory activities need by the tested AD framework.
-
void CalculateObjective(int times)
Repeatedly computes the objective function
times
times for the stored input. Stores results. -
void CalculateJacobian(int times)
Repeatedly computes the Jacobian of the objective function
times
times for the stored input. Stores results. -
TOutput Output()
Converts internally saved outputs into the format specified by the runner.
-
-
Decorate each such class with an
Export
attribute:[Export(typeof<DotnetRunner.ITest<TInput, TOutput>>)]
where
T
is still an objective type here.This will allow the runner to load these classes using MEF.
-
Add your module to common dotnet module tests project (see below).
-
Add your module to the global runner script.
We use xUnit framework to test .NET Core assemblies.
AD Bench already contains some tests for each objective. When you add a new module, the first thing you should do is to test your module with the existing tests. Follow these steps for every objective you want to test:
-
Add a reference to your project in
/test/dotnet/modules/DotnetModulesTests.csproj
<ProjectReference Include="..\..\..\src\dotnet\modules\DiffSharpModule\DiffSharpModule.fsproj"> <Private>true</Private> </ProjectReference>
Note the
Private
flag - it's needed to ensure, that your module will be copied locally for the test project, which is needed to test the dynamic loading. -
Open
/test/dotnet/modules/TTests.cs
whereT
is the short name of the tested objective. You will see the following lines:public static IEnumerable<object[]> TestParameterSet { get; } = new[] { new ModuleTestParameters("./DiffSharpModule.dll", 1e-10 ), ... }.Select(m => new object[] { m }).ToArray();
-
Add a
ModuleTestParameters
object for your module to the list. Arguments of the constructor here are the name of the assembly with your module and atolerance
for the test results.public static IEnumerable<object[]> TestParameterSet { get; } = new[] { new ModuleTestParameters("./DiffSharpModule.dll", 1e-10 ), ... new ModuleTestParameters("./YourModule.dll", absoluteTolerance ) }.Select(m => new object[] { m }).ToArray();
tolerance
is a number used to compare results produced by the current module with the correct results. If an absolute difference between at least one of them exceeds this value then the test is failed.
Follow these steps to add a new test case for an existing objective that will be shared by all modules:
- Open
/test/dotnet/modules/TTests.cs
whereT
is the short name of the testing objective. - Add the following lines to the end of the
TTests
class:There you can test the behavior of the[Theory] [MemberData(nameof(TestParameterSet))] public void TestCaseName(ModuleTestParameters testParameters) { using (var moduleLoader = new ModuleLoader(testParameters.ModuleName)) { var test = moduleLoader.GetTTest(); ... test code ... } }
ITest<TInput, TOutput> test
object. The test will run for all modules listed inTestParameterSet
.
To create a common test suite for a new objective create /test/dotnet/modules/TTests.cs
with the following content:
using DotnetRunner;
using DotnetRunner.Data;
using System.Collections.Generic;
using System.Linq;
using Xunit;
namespace DotnetModulesTests
{
public class TTests
{
public static IEnumerable<object[]> TestParameterSet { get; } = new[]
{
new ModuleTestParameters("./ModuleName1.dll", 1e-10 ),
new ModuleTestParameters("./ModuleName2.dll", 1e-10 ),
...
}.Select(m => new object[] { m }).ToArray();
}
}
In the TestParameterSet
list the modules that support your objective and respective allowed tolerances. Create test cases as described in the "Adding a new common test case" section.