Use all passed devices when linking program

Related-To: NEO-5001
Change-Id: I3944375023b9cb3322df83e6e042ba8be2bd762c
Signed-off-by: Mateusz Jablonski <mateusz.jablonski@intel.com>
This commit is contained in:
Mateusz Jablonski
2020-10-28 17:18:37 +01:00
committed by sys_ocldev
parent 17970ad5e7
commit 430cca3f4c
11 changed files with 397 additions and 119 deletions

View File

@ -20,10 +20,10 @@
#include "cl_api_tests.h"
using namespace NEO;
typedef api_tests clGetProgramBuildInfoTests;
namespace ULT {
void verifyDevices(cl_program pProgram, size_t expectedNumDevices, cl_device_id *expectedDevices);
TEST_F(clGetProgramBuildInfoTests, givenSourceWhenclGetProgramBuildInfoIsCalledThenReturnClBuildNone) {
cl_program pProgram = nullptr;
@ -278,4 +278,177 @@ TEST_F(clGetProgramBuildInfoTests, givenInvalidDeviceInputWhenGetProgramBuildInf
retVal = clGetProgramBuildInfo(pProgram, context.getDevice(0), CL_PROGRAM_BUILD_STATUS, sizeof(buildStatus), &buildStatus, nullptr);
EXPECT_EQ(CL_INVALID_DEVICE, retVal);
}
TEST(clGetProgramBuildInfoTest, givenMultiDeviceProgramWhenLinkingForSpecificDevicesThenOnlySpecificDevicesReportBuildStatus) {
MockProgram *pProgram = nullptr;
std::unique_ptr<char[]> pSource = nullptr;
size_t sourceSize = 0;
std::string testFile;
KernelBinaryHelper kbHelper("CopyBuffer_simd16");
testFile.append(clFiles);
testFile.append("CopyBuffer_simd16.cl");
pSource = loadDataFromFile(
testFile.c_str(),
sourceSize);
ASSERT_NE(0u, sourceSize);
ASSERT_NE(nullptr, pSource);
const char *sources[1] = {pSource.get()};
MockUnrestrictiveContextMultiGPU context;
cl_int retVal = CL_INVALID_PROGRAM;
pProgram = Program::create<MockProgram>(
&context,
1,
sources,
&sourceSize,
retVal);
EXPECT_NE(nullptr, pProgram);
ASSERT_EQ(CL_SUCCESS, retVal);
cl_build_status buildStatus;
for (const auto &device : context.getDevices()) {
retVal = clGetProgramBuildInfo(pProgram, device, CL_PROGRAM_BUILD_STATUS, sizeof(buildStatus), &buildStatus, NULL);
EXPECT_EQ(CL_SUCCESS, retVal);
EXPECT_EQ(CL_BUILD_NONE, buildStatus);
}
retVal = clCompileProgram(
pProgram,
0,
nullptr,
nullptr,
0,
nullptr,
nullptr,
nullptr,
nullptr);
ASSERT_EQ(CL_SUCCESS, retVal);
pProgram->setBuildStatus(CL_BUILD_NONE);
cl_device_id devicesForLinking[] = {context.getDevice(1), context.getDevice(3)};
cl_program programForLinking = pProgram;
auto outProgram = clLinkProgram(
&context,
2,
devicesForLinking,
nullptr,
1,
&programForLinking,
nullptr,
nullptr,
&retVal);
ASSERT_EQ(CL_SUCCESS, retVal);
EXPECT_NE(nullptr, outProgram);
verifyDevices(outProgram, 2, devicesForLinking);
for (const auto &device : devicesForLinking) {
retVal = clGetProgramBuildInfo(outProgram, device, CL_PROGRAM_BUILD_STATUS, sizeof(buildStatus), &buildStatus, NULL);
EXPECT_EQ(CL_SUCCESS, retVal);
EXPECT_EQ(CL_BUILD_SUCCESS, buildStatus);
}
retVal = clReleaseProgram(pProgram);
EXPECT_EQ(CL_SUCCESS, retVal);
retVal = clReleaseProgram(outProgram);
EXPECT_EQ(CL_SUCCESS, retVal);
}
TEST(clGetProgramBuildInfoTest, givenMultiDeviceProgramWhenLinkingWithoutInputDevicesThenAllDevicesReportBuildStatus) {
MockProgram *pProgram = nullptr;
std::unique_ptr<char[]> pSource = nullptr;
size_t sourceSize = 0;
std::string testFile;
KernelBinaryHelper kbHelper("CopyBuffer_simd16");
testFile.append(clFiles);
testFile.append("CopyBuffer_simd16.cl");
pSource = loadDataFromFile(
testFile.c_str(),
sourceSize);
ASSERT_NE(0u, sourceSize);
ASSERT_NE(nullptr, pSource);
const char *sources[1] = {pSource.get()};
MockUnrestrictiveContextMultiGPU context;
cl_int retVal = CL_INVALID_PROGRAM;
pProgram = Program::create<MockProgram>(
&context,
1,
sources,
&sourceSize,
retVal);
EXPECT_NE(nullptr, pProgram);
ASSERT_EQ(CL_SUCCESS, retVal);
cl_build_status buildStatus;
for (const auto &device : context.getDevices()) {
retVal = clGetProgramBuildInfo(pProgram, device, CL_PROGRAM_BUILD_STATUS, sizeof(buildStatus), &buildStatus, NULL);
EXPECT_EQ(CL_SUCCESS, retVal);
EXPECT_EQ(CL_BUILD_NONE, buildStatus);
}
retVal = clCompileProgram(
pProgram,
0,
nullptr,
nullptr,
0,
nullptr,
nullptr,
nullptr,
nullptr);
ASSERT_EQ(CL_SUCCESS, retVal);
pProgram->setBuildStatus(CL_BUILD_NONE);
cl_program programForLinking = pProgram;
auto outProgram = clLinkProgram(
&context,
0,
nullptr,
nullptr,
1,
&programForLinking,
nullptr,
nullptr,
&retVal);
ASSERT_EQ(CL_SUCCESS, retVal);
EXPECT_NE(nullptr, outProgram);
std::vector<cl_device_id> contextDevices;
context.getDevices().toDeviceIDs(contextDevices);
verifyDevices(outProgram, contextDevices.size(), contextDevices.data());
for (const auto &device : context.getDevices()) {
retVal = clGetProgramBuildInfo(outProgram, device, CL_PROGRAM_BUILD_STATUS, sizeof(buildStatus), &buildStatus, NULL);
EXPECT_EQ(CL_SUCCESS, retVal);
EXPECT_EQ(CL_BUILD_SUCCESS, buildStatus);
}
retVal = clReleaseProgram(pProgram);
EXPECT_EQ(CL_SUCCESS, retVal);
retVal = clReleaseProgram(outProgram);
EXPECT_EQ(CL_SUCCESS, retVal);
}
} // namespace ULT

View File

@ -206,7 +206,7 @@ TEST_F(clLinkProgramTests, GivenProgramsWithSpecConstantsThenSpecConstantsAreEmb
MockCompilerDebugVars igcDebugVars;
igcDebugVars.receivedInput = &receivedInput;
gEnvironment->igcPushDebugVars(igcDebugVars);
progDst->link(0U, nullptr, "", 3, inputPrograms);
progDst->link(progDst->getDevices(), "", 3, inputPrograms);
gEnvironment->igcPopDebugVars();
std::string elfDecodeError;
@ -374,4 +374,110 @@ TEST_F(clLinkProgramTests, GivenValidCallbackInputWhenLinkProgramThenCallbackIsI
EXPECT_EQ(CL_SUCCESS, retVal);
}
TEST_F(clLinkProgramTests, givenMultiDeviceProgramWhenLinkingForInvalidDevicesInputThenInvalidDeviceErrorIsReturned) {
cl_program pProgram = nullptr;
size_t sourceSize = 0;
std::string testFile;
testFile.append(clFiles);
testFile.append("copybuffer.cl");
auto pSource = loadDataFromFile(
testFile.c_str(),
sourceSize);
ASSERT_NE(0u, sourceSize);
ASSERT_NE(nullptr, pSource);
const char *sources[1] = {pSource.get()};
pProgram = clCreateProgramWithSource(
pContext,
1,
sources,
&sourceSize,
&retVal);
EXPECT_NE(nullptr, pProgram);
ASSERT_EQ(CL_SUCCESS, retVal);
retVal = clCompileProgram(
pProgram,
1,
&testedClDevice,
nullptr,
0,
nullptr,
nullptr,
nullptr,
nullptr);
ASSERT_EQ(CL_SUCCESS, retVal);
cl_program program = pProgram;
cl_program outProgram;
MockContext mockContext;
cl_device_id nullDeviceInput[] = {pContext->getDevice(0), nullptr};
cl_device_id notAssociatedDeviceInput[] = {mockContext.getDevice(0)};
cl_device_id validDeviceInput[] = {pContext->getDevice(0)};
outProgram = clLinkProgram(
pContext,
0,
validDeviceInput,
nullptr,
1,
&program,
nullptr,
nullptr,
&retVal);
EXPECT_EQ(CL_INVALID_VALUE, retVal);
EXPECT_EQ(nullptr, outProgram);
outProgram = clLinkProgram(
pContext,
1,
nullptr,
nullptr,
1,
&program,
nullptr,
nullptr,
&retVal);
EXPECT_EQ(CL_INVALID_VALUE, retVal);
EXPECT_EQ(nullptr, outProgram);
outProgram = clLinkProgram(
pContext,
2,
nullDeviceInput,
nullptr,
1,
&program,
nullptr,
nullptr,
&retVal);
EXPECT_EQ(CL_INVALID_DEVICE, retVal);
EXPECT_EQ(nullptr, outProgram);
outProgram = clLinkProgram(
pContext,
1,
notAssociatedDeviceInput,
nullptr,
1,
&program,
nullptr,
nullptr,
&retVal);
EXPECT_EQ(CL_INVALID_DEVICE, retVal);
EXPECT_EQ(nullptr, outProgram);
retVal = clReleaseProgram(pProgram);
EXPECT_EQ(CL_SUCCESS, retVal);
}
} // namespace ULT

View File

@ -1113,7 +1113,7 @@ TEST_F(ProgramTests, GivenFlagsWhenLinkingProgramThenBuildOptionsHaveBeenApplied
pDevice->getExecutionEnvironment()->rootDeviceEnvironments[pDevice->getRootDeviceIndex()]->compilerInterface.reset(cip);
retVal = pProgram->link(0, nullptr, options.c_str(), 1, &program);
retVal = pProgram->link(pProgram->getDevices(), options.c_str(), 1, &program);
EXPECT_EQ(CL_SUCCESS, retVal);
// Check build options that were applied
@ -1182,7 +1182,6 @@ TEST_P(ProgramFromSourceTest, GivenSpecificParamatersWhenLinkingProgramThenSucce
&usedDevice,
SourceFileName);
cl_device_id deviceList = {0};
cl_program program = pProgram;
cl_program nullprogram = nullptr;
cl_program invprogram = (cl_program)pContext;
@ -1190,36 +1189,25 @@ TEST_P(ProgramFromSourceTest, GivenSpecificParamatersWhenLinkingProgramThenSucce
// Order of following microtests is important - do not change.
// Add new microtests at end.
// invalid link parameters: combinations of numDevices & deviceList
retVal = pProgram->link(1, nullptr, nullptr, 1, &program);
EXPECT_EQ(CL_INVALID_VALUE, retVal);
retVal = pProgram->link(0, &deviceList, nullptr, 1, &program);
EXPECT_EQ(CL_INVALID_VALUE, retVal);
// invalid link parameters: combinations of numInputPrograms & inputPrograms
retVal = pProgram->link(0, nullptr, nullptr, 0, &program);
retVal = pProgram->link(pProgram->getDevices(), nullptr, 0, &program);
EXPECT_EQ(CL_INVALID_VALUE, retVal);
retVal = pProgram->link(0, nullptr, nullptr, 1, nullptr);
retVal = pProgram->link(pProgram->getDevices(), nullptr, 1, nullptr);
EXPECT_EQ(CL_INVALID_VALUE, retVal);
// invalid link parameters: invalid content of deviceList
retVal = pProgram->link(1, &deviceList, nullptr, 1, &program);
EXPECT_EQ(CL_INVALID_DEVICE, retVal);
// fail linking - another linking is already in progress
pProgram->setBuildStatus(CL_BUILD_IN_PROGRESS);
retVal = pProgram->link(0, nullptr, nullptr, 1, &program);
retVal = pProgram->link(pProgram->getDevices(), nullptr, 1, &program);
EXPECT_EQ(CL_INVALID_OPERATION, retVal);
pProgram->setBuildStatus(CL_BUILD_NONE);
// invalid link parameters: invalid Program object==nullptr
retVal = pProgram->link(0, nullptr, nullptr, 1, &nullprogram);
retVal = pProgram->link(pProgram->getDevices(), nullptr, 1, &nullprogram);
EXPECT_EQ(CL_INVALID_PROGRAM, retVal);
// invalid link parameters: invalid Program object==non Program object
retVal = pProgram->link(0, nullptr, nullptr, 1, &invprogram);
retVal = pProgram->link(pProgram->getDevices(), nullptr, 1, &invprogram);
EXPECT_EQ(CL_INVALID_PROGRAM, retVal);
// compile successfully a kernel to be linked later
@ -1232,29 +1220,29 @@ TEST_P(ProgramFromSourceTest, GivenSpecificParamatersWhenLinkingProgramThenSucce
pProgram->irBinary.release();
size_t irBinSize = pProgram->irBinarySize;
pProgram->setIrBinary(nullptr, false);
retVal = pProgram->link(0, nullptr, nullptr, 1, &program);
retVal = pProgram->link(pProgram->getDevices(), nullptr, 1, &program);
EXPECT_EQ(CL_INVALID_PROGRAM, retVal);
pProgram->setIrBinary(pIrBin, isSpirvTmp);
// fail linking - size of code to be linked is == 0
pProgram->setIrBinarySize(0, isSpirvTmp);
retVal = pProgram->link(0, nullptr, nullptr, 1, &program);
retVal = pProgram->link(pProgram->getDevices(), nullptr, 1, &program);
EXPECT_EQ(CL_INVALID_PROGRAM, retVal);
pProgram->setIrBinarySize(irBinSize, isSpirvTmp);
// fail linking - any link error (here caused by specifying unrecognized option)
retVal = pProgram->link(0, nullptr, "-invalid-option", 1, &program);
retVal = pProgram->link(pProgram->getDevices(), "-invalid-option", 1, &program);
EXPECT_EQ(CL_LINK_PROGRAM_FAILURE, retVal);
// fail linking - linked code is corrupted and cannot be postprocessed
auto device = static_cast<ClDevice *>(usedDevice);
auto p2 = std::make_unique<FailingGenBinaryProgram>(toClDeviceVector(*device));
retVal = p2->link(0, nullptr, nullptr, 1, &program);
retVal = p2->link(p2->getDevices(), nullptr, 1, &program);
EXPECT_EQ(CL_INVALID_BINARY, retVal);
p2.reset(nullptr);
// link successfully
retVal = pProgram->link(0, nullptr, nullptr, 1, &program);
retVal = pProgram->link(pProgram->getDevices(), nullptr, 1, &program);
EXPECT_EQ(CL_SUCCESS, retVal);
}
@ -1269,11 +1257,11 @@ TEST_P(ProgramFromSourceTest, GivenInvalidOptionsWhenCreatingLibraryThenCorrectE
EXPECT_EQ(CL_SUCCESS, retVal);
// create library successfully
retVal = pProgram->link(0, nullptr, CompilerOptions::createLibrary.data(), 1, &program);
retVal = pProgram->link(pProgram->getDevices(), CompilerOptions::createLibrary.data(), 1, &program);
EXPECT_EQ(CL_SUCCESS, retVal);
// fail library creation - any link error (here caused by specifying unrecognized option)
retVal = pProgram->link(0, nullptr, CompilerOptions::concatenate(CompilerOptions::createLibrary, "-invalid-option").c_str(), 1, &program);
retVal = pProgram->link(pProgram->getDevices(), CompilerOptions::concatenate(CompilerOptions::createLibrary, "-invalid-option").c_str(), 1, &program);
EXPECT_EQ(CL_LINK_PROGRAM_FAILURE, retVal);
auto device = pContext->getDevice(0);
@ -1283,7 +1271,7 @@ TEST_P(ProgramFromSourceTest, GivenInvalidOptionsWhenCreatingLibraryThenCorrectE
auto failingProgram = std::make_unique<MockProgram>(toClDeviceVector(*device));
// fail library creation - CompilerInterface cannot be obtained
retVal = failingProgram->link(0, nullptr, CompilerOptions::createLibrary.data(), 1, &program);
retVal = failingProgram->link(failingProgram->getDevices(), CompilerOptions::createLibrary.data(), 1, &program);
EXPECT_EQ(CL_OUT_OF_HOST_MEMORY, retVal);
std::swap(rootDeviceEnvironment, executionEnvironment->rootDeviceEnvironments[device->getRootDeviceIndex()]);
}
@ -2335,7 +2323,7 @@ TEST_F(ProgramTests, WhenLinkingTwoValidSpirvProgramsThenValidProgramIsReturned)
EXPECT_EQ(CL_SUCCESS, errCode);
cl_program linkNodes[] = {node1, node2};
errCode = prog->link(0, nullptr, nullptr, 2, linkNodes);
errCode = prog->link(prog->getDevices(), nullptr, 2, linkNodes);
EXPECT_EQ(CL_SUCCESS, errCode);
prog->release();
@ -2886,7 +2874,6 @@ TEST_F(ProgramBinTest, GivenBuildWithDebugDataThenBuildDataAvailableViaGetInfo)
TEST_F(ProgramBinTest, GivenDebugDataAvailableWhenLinkingProgramThenDebugDataIsStoredInProgram) {
DebugDataGuard debugDataGuard;
cl_device_id device = pClDevice;
const char *sourceCode = "__kernel void\nCB(\n__global unsigned int* src, __global unsigned int* dst)\n{\nint id = (int)get_global_id(0);\ndst[id] = src[id];\n}\n";
pProgram = Program::create<MockProgram>(
pContext,
@ -2899,7 +2886,7 @@ TEST_F(ProgramBinTest, GivenDebugDataAvailableWhenLinkingProgramThenDebugDataIsS
EXPECT_EQ(CL_SUCCESS, retVal);
cl_program programToLink = pProgram;
retVal = pProgram->link(1, &device, nullptr, 1, &programToLink);
retVal = pProgram->link(pProgram->getDevices(), nullptr, 1, &programToLink);
EXPECT_EQ(CL_SUCCESS, retVal);
EXPECT_NE(nullptr, pProgram->getDebugData());
@ -2965,7 +2952,6 @@ class MockCompilerInterfaceWithGtpinParam : public CompilerInterface {
};
TEST_F(ProgramBinTest, GivenSourceKernelWhenLinkingProgramThenGtpinInitInfoIsPassed) {
cl_device_id device = pClDevice;
void *pIgcInitPtr = reinterpret_cast<void *>(0x1234);
gtpinSetIgcInit(pIgcInitPtr);
const char *sourceCode = "__kernel void\nCB(\n__global unsigned int* src, __global unsigned int* dst)\n{\nint id = (int)get_global_id(0);\ndst[id] = src[id];\n}\n";
@ -2982,7 +2968,7 @@ TEST_F(ProgramBinTest, GivenSourceKernelWhenLinkingProgramThenGtpinInitInfoIsPas
pDevice->getExecutionEnvironment()->rootDeviceEnvironments[pDevice->getRootDeviceIndex()]->compilerInterface.reset(mockCompilerInterface.get());
cl_program programToLink = pProgram;
retVal = pProgram->link(1, &device, nullptr, 1, &programToLink);
retVal = pProgram->link(pProgram->getDevices(), nullptr, 1, &programToLink);
EXPECT_EQ(pIgcInitPtr, mockCompilerInterface->gtpinInfoPassed);
mockCompilerInterface.release();

View File

@ -104,7 +104,7 @@ TEST_F(ProgramWithBlockKernelsTest, GivenKernelWithBlockKernelsWhenProgramIsLink
EXPECT_EQ(CL_SUCCESS, retVal);
retVal = programLinked->link(1, &device, buildOptions, 1, &program);
retVal = programLinked->link(pProgram->getDevices(), buildOptions, 1, &program);
EXPECT_EQ(CL_SUCCESS, retVal);
BlockKernelManager *blockManager = programLinked->getBlockKernelManager();

View File

@ -185,7 +185,7 @@ TEST_F(ProgramWithKernelDebuggingTest, givenEnabledKernelDebugWhenProgramIsLinke
EXPECT_CALL(*program, appendKernelDebugOptions()).Times(1);
cl_program clProgramToLink = pProgram;
retVal = program->link(1, &device, nullptr, 1, &clProgramToLink);
retVal = program->link(pProgram->getDevices(), nullptr, 1, &clProgramToLink);
EXPECT_EQ(CL_SUCCESS, retVal);
}
@ -222,7 +222,7 @@ TEST_F(ProgramWithKernelDebuggingTest, givenEnabledKernelDebugWhenProgramIsLinke
EXPECT_EQ(CL_SUCCESS, retVal);
cl_program program = pProgram;
retVal = pProgram->link(1, &device, nullptr,
retVal = pProgram->link(pProgram->getDevices(), nullptr,
1, &program);
EXPECT_EQ(CL_SUCCESS, retVal);
}