Add 'projects/rocr-runtime/' from commit '72061a9024139fa0a99f73f9d3d4deb275670095'
git-subtree-dir: projects/rocr-runtime git-subtree-mainline:ad0fb25ed5git-subtree-split:72061a9024
This commit is contained in:
@@ -0,0 +1,7 @@
|
||||
OPENCL_DEPTH = ../../..
|
||||
|
||||
include $(OPENCL_DEPTH)/runtimenew/runtimedefs
|
||||
|
||||
SUBDIRS = build
|
||||
|
||||
include $(OPENCL_DEPTH)/runtimenew/runtimerules
|
||||
@@ -0,0 +1,8 @@
|
||||
OPENCL_DEPTH = ../../../..
|
||||
|
||||
include $(OPENCL_DEPTH)/hsadefs
|
||||
|
||||
BUILD_SUBDIRS = $(DEFAULT_TARGETS)
|
||||
BUILD_MAKEFILE = Makefile.get_info
|
||||
|
||||
include $(OPENCL_DEPTH)/hsarules
|
||||
@@ -0,0 +1,107 @@
|
||||
include $(OPENCL_DEPTH)/hsadefs
|
||||
|
||||
|
||||
# Executable containing all the API core tests
|
||||
EXE_TARGET = HsaGetInfo
|
||||
|
||||
#
|
||||
# Makefile construct to copy executable to Dist folder
|
||||
#
|
||||
DIST_BIN_TARGET = $(EXE_TARGET)
|
||||
ifdef ATI_OS_WINDOWS
|
||||
DIST_BIN_TARGETS = $(EXE_TARGET)$(EXE_EXT)
|
||||
endif
|
||||
|
||||
ifdef ATI_BITS_64
|
||||
LIB_SUFFIX=64
|
||||
BITS=64
|
||||
CMPILERBITS=64
|
||||
else
|
||||
LIB_SUFFIX=
|
||||
BITS=
|
||||
ifdef ATI_OS_WINDOWS
|
||||
CMPILERBITS=
|
||||
else
|
||||
CMPILERBITS=32
|
||||
endif
|
||||
endif
|
||||
|
||||
ifdef ATI_OS_WINDOWS
|
||||
LFLAGS += /subsystem:console
|
||||
CORE_LIB=dll
|
||||
LIB_PREFIX=
|
||||
DYN_LIB_EXT=$(LIB_EXT)
|
||||
UTIL_EXT=win
|
||||
else
|
||||
LIB_PREFIX=lib
|
||||
CORE_LIB=so
|
||||
DYN_LIB_EXT=$(DLL_EXT)
|
||||
UTIL_EXT=
|
||||
endif
|
||||
|
||||
LCXXDEFS += -DAMD_INTERNAL_BUILD
|
||||
|
||||
vpath %.cpp $(COMPONENT_DEPTH)
|
||||
CPPFILES := $(notdir $(wildcard $(COMPONENT_DEPTH)/*.cpp))
|
||||
|
||||
TOOLS_TEST_COMMON=$(COMPONENT_DEPTH)/../common
|
||||
vpath %.cpp $(TOOLS_TEST_COMMON)
|
||||
CPPFILES += $(notdir $(wildcard $(TOOLS_TEST_COMMON)/*.cpp))
|
||||
|
||||
|
||||
ifdef ATI_OS_LINUX
|
||||
GCXXOPTS := $(filter-out -fno-rtti,$(GCXXOPTS))
|
||||
GCXXOPTS := $(filter-out -fno-exceptions,$(GCXXOPTS))
|
||||
LFLAGS += -L$(DIST_LIB_DEST) -lpthread $(LIBSTDCXX) -lm -ldl -lrt -lstdc++
|
||||
#LFLAGS += -L$(DIST_LIB_DEST) -lpthread $(LIBSTDCXX) -lm -ldl -lrt
|
||||
endif
|
||||
|
||||
SC_DIR_NAME ?= finalizer
|
||||
export HT_DEPTH=$(OPENCL_DEPTH)/compiler/$(SC_DIR_NAME)/HSAIL/hsail-tools
|
||||
include $(HT_DEPTH)/htlibs
|
||||
|
||||
#LCINCS := $(INCSWITCH) "$(OPENCL_DEPTH)/contrib/gtest-1.6.0/include"
|
||||
LCINCS += $(INCSWITCH) "$(OPENCL_DEPTH)/runtime"
|
||||
LCINCS += $(INCSWITCH) "$(OPENCL_DEPTH)/runtime/samples"
|
||||
LCINCS += $(INCSWITCH) "$(OPENCL_DEPTH)/contrib/elftoolchain/libelf"
|
||||
LCINCS += $(INCSWITCH) "$(OPENCL_DEPTH)/contrib/elftoolchain/common"
|
||||
LCINCS += $(INCSWITCH) "$(OPENCL_DEPTH)/runtime/inc"
|
||||
LCINCS += $(LIBHSAIL_INCS) $(LIBHSAIL_AMD_INCS)
|
||||
|
||||
LCINCS += $(INCSWITCH) "$(OPENCL_PATH)/compiler/lib/include"
|
||||
LCINCS += $(INCSWITCH) "$(OPENCL_DEPTH)/runtime/samples/common"
|
||||
|
||||
UTIL_BUILD=build/$(OS_TYPE)/util/$(UTIL_EXT)/$(BUILD_DIR)
|
||||
#LLLIBS += $(OPENCL_DEPTH)/runtime/core/$(UTIL_BUILD)/util$(UTIL_EXT)$(LIB_EXT)
|
||||
|
||||
|
||||
LIBELF_DIR=build/$(OS_TYPE)/$(BUILD_DIR)
|
||||
RUNTIME_BUILD=build/$(OS_TYPE)/$(CORE_LIB)/$(BUILD_DIR)
|
||||
ifdef ATI_OS_LINUX
|
||||
GCXXOPTS := $(filter-out -fno-exceptions,$(GCXXOPTS))
|
||||
LFLAGS += -L$(DIST_LIB_DEST) -lpthread $(LIBSTDCXX) -lm -ldl -lrt
|
||||
LFLAGS += -L$(OPENCL_DEPTH)/contrib/elftoolchain/libelf/$(LIBELF_DIR) -lelf
|
||||
LFLAGS += -L$(OPENCL_DEPTH)/runtime/core/$(RUNTIME_BUILD) -lhsa-runtime$(LIB_SUFFIX)
|
||||
LFLAGS += -L$(OPENCL_DEPTH)/runtime/tools/$(RUNTIME_BUILD) -lhsa-runtime-tools$(LIB_SUFFIX)
|
||||
else
|
||||
# Verify the extension of libelf is valid i.e. is not dll but instead is "lib"
|
||||
#LLLIBS += -L$(OPENCL_DEPTH)/contrib/elftoolchain/libelf/$(LIBELF_DIR)/libelf
|
||||
LLLIBS += $(OPENCL_DEPTH)/runtime/core/$(RUNTIME_BUILD)/hsa-runtime$(LIB_SUFFIX)$(LIB_EXT)
|
||||
LLLIBS += $(OPENCL_DEPTH)/runtime/tools/$(RUNTIME_BUILD)/hsa-runtime-tools$(LIB_SUFFIX)$(LIB_EXT)
|
||||
endif
|
||||
LLLIBS += $(LIBHSAIL_USER_LIBS)
|
||||
|
||||
#
|
||||
# Copy the Hsa ample to Hsa distribution folder
|
||||
#
|
||||
ifdef ATI_OS_LINUX
|
||||
LOCAL_TARGETS = inst_sample_copy
|
||||
endif
|
||||
inst_sample_copy:
|
||||
$(MKDIR) $(DIST_BIN_DEST)/../../samples/$(OS_TYPE)
|
||||
-$(RM) -f $(DIST_BIN_DEST)/../../samples/$(OS_TYPE)/$(EXE_TARGET)
|
||||
$(CP) $(BUILD_DIR)/$(EXE_TARGET) $(DIST_BIN_DEST)/../../samples/$(OS_TYPE)
|
||||
|
||||
|
||||
include $(OPENCL_DEPTH)/hsarules
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
#include "get_info.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
GetInfo::GetInfo() : HsaTest("HSA Info") {}
|
||||
|
||||
GetInfo::~GetInfo() {}
|
||||
|
||||
void GetInfo::Run() {
|
||||
std::cout << std::endl;
|
||||
std::cout << "Num CPUs in platform: " << cpus_.size() << std::endl;
|
||||
std::cout << "------------------------------------------------\n";
|
||||
|
||||
for (size_t i = 0; i < cpus_.size(); ++i) {
|
||||
hsa_agent_t cpu = cpus_[i];
|
||||
std::cout << "CPU[" << i << "] properties:" << std::endl;
|
||||
std::cout << "------------------------------------------------\n";
|
||||
AgentProps prop(cpu);
|
||||
PrintAgentInfo(prop);
|
||||
PrintPeers(cpu);
|
||||
std::cout << "------------------------------------------------\n";
|
||||
|
||||
hsa_amd_memory_pool_t global_fine = global_fine_[cpu.handle];
|
||||
if (global_fine.handle != 0) {
|
||||
std::cout << "CPU[" << i << "] system fine grain pool properties:\n";
|
||||
std::cout << "------------------------------------------------\n";
|
||||
PoolProps prop(global_fine);
|
||||
PrintPoolInfo(prop);
|
||||
std::cout << "------------------------------------------------\n";
|
||||
}
|
||||
|
||||
hsa_amd_memory_pool_t global_coarse = global_coarse_[cpu.handle];
|
||||
if (global_coarse.handle != 0) {
|
||||
std::cout << "CPU[" << i << "] system coarse grain pool properties:\n";
|
||||
std::cout << "------------------------------------------------\n";
|
||||
PoolProps prop(global_coarse);
|
||||
PrintPoolInfo(prop);
|
||||
std::cout << "------------------------------------------------\n";
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << std::endl;
|
||||
std::cout << "Num GPUs in platform: " << gpus_.size() << std::endl;
|
||||
std::cout << "------------------------------------------------\n";
|
||||
|
||||
for (size_t i = 0; i < gpus_.size(); ++i) {
|
||||
hsa_agent_t gpu = gpus_[i];
|
||||
std::cout << "GPU[" << i << "] properties:" << std::endl;
|
||||
std::cout << "------------------------------------------------\n";
|
||||
AgentProps prop(gpu);
|
||||
PrintAgentInfo(prop);
|
||||
PrintPeers(gpu);
|
||||
std::cout << "------------------------------------------------\n";
|
||||
|
||||
hsa_amd_memory_pool_t global_coarse = global_coarse_[gpu.handle];
|
||||
if (global_coarse.handle != 0) {
|
||||
std::cout << "GPU[" << i << "] local memory pool properties:\n";
|
||||
std::cout << "------------------------------------------------\n";
|
||||
PoolProps prop(global_coarse);
|
||||
PrintPoolInfo(prop);
|
||||
std::cout << "------------------------------------------------\n";
|
||||
}
|
||||
|
||||
hsa_amd_memory_pool_t group = group_[gpu.handle];
|
||||
if (group.handle != 0) {
|
||||
std::cout << "GPU[" << i << "] group memory pool properties:\n";
|
||||
std::cout << "------------------------------------------------\n";
|
||||
PoolProps prop(group);
|
||||
PrintPoolInfo(prop);
|
||||
std::cout << "------------------------------------------------\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
GetInfo get_info;
|
||||
|
||||
get_info.Init();
|
||||
get_info.Run();
|
||||
get_info.Cleanup();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
#ifndef GET_INFO_H
|
||||
#define GET_INFO_H
|
||||
|
||||
#include "samples/common/hsa_test.h"
|
||||
|
||||
class GetInfo : public HsaTest {
|
||||
public:
|
||||
GetInfo();
|
||||
~GetInfo();
|
||||
|
||||
void Run() override;
|
||||
};
|
||||
|
||||
#endif // GET_INFO_H
|
||||
@@ -0,0 +1,17 @@
|
||||
OPENCL_DEPTH = ../..
|
||||
|
||||
include $(OPENCL_DEPTH)/hsadefs
|
||||
|
||||
SUBDIRS = NBody
|
||||
SUBDIRS += DwtHarr1D
|
||||
SUBDIRS += BitonicSort
|
||||
SUBDIRS += BinarySearch
|
||||
SUBDIRS += BlackScholes
|
||||
SUBDIRS += FloydWarshall
|
||||
SUBDIRS += FastWalshTransform
|
||||
SUBDIRS += MatrixTranspose
|
||||
SUBDIRS += MatrixMultiplication
|
||||
SUBDIRS += MonteCarloAsian
|
||||
SUBDIRS += SimpleConvolution
|
||||
|
||||
include $(OPENCL_DEPTH)/hsarules
|
||||
@@ -0,0 +1,48 @@
|
||||
#include "common.hpp"
|
||||
|
||||
void ErrorCheck(hsa_status_t hsa_error_code) {
|
||||
if (hsa_error_code != HSA_STATUS_SUCCESS) {
|
||||
std::cerr << "HSA reported error!" << std::endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
hsa_status_t FindGpuDevice(hsa_agent_t agent, void *data) {
|
||||
if (data == NULL) {
|
||||
return HSA_STATUS_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
hsa_device_type_t hsa_device_type;
|
||||
hsa_status_t hsa_error_code = hsa_agent_get_info(
|
||||
agent, HSA_AGENT_INFO_DEVICE, &hsa_device_type
|
||||
);
|
||||
if (hsa_error_code != HSA_STATUS_SUCCESS) {
|
||||
return hsa_error_code;
|
||||
}
|
||||
|
||||
if (hsa_device_type == HSA_DEVICE_TYPE_GPU) {
|
||||
*((hsa_agent_t*)data) = agent;
|
||||
}
|
||||
|
||||
return HSA_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
hsa_status_t FindHostRegion(hsa_region_t region, void *data) {
|
||||
if (data == NULL) {
|
||||
return HSA_STATUS_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
bool is_host_region = false;
|
||||
hsa_status_t hsa_error_code = hsa_region_get_info(
|
||||
region, (hsa_region_info_t)HSA_AMD_REGION_INFO_HOST_ACCESSIBLE,
|
||||
&is_host_region);
|
||||
if (hsa_error_code != HSA_STATUS_SUCCESS) {
|
||||
return hsa_error_code;
|
||||
}
|
||||
|
||||
if (is_host_region) {
|
||||
*((hsa_region_t*)data) = region;
|
||||
}
|
||||
|
||||
return HSA_STATUS_SUCCESS;
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
#ifndef COMMON_COMMON_HPP
|
||||
#define COMMON_COMMON_HPP
|
||||
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
|
||||
#include "hsa.h"
|
||||
#include "hsa_ext_finalize.h"
|
||||
#include "hsa_ext_amd.h"
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#define ALIGNED_(x) __declspec(align(x))
|
||||
#else
|
||||
#if defined(__GNUC__)
|
||||
#define ALIGNED_(x) __attribute__ ((aligned(x)))
|
||||
#endif // __GNUC__
|
||||
#endif // _MSC_VER
|
||||
|
||||
#define MULTILINE(...) # __VA_ARGS__
|
||||
|
||||
void ErrorCheck(hsa_status_t hsa_error_code);
|
||||
|
||||
hsa_status_t FindGpuDevice(hsa_agent_t agent, void *data);
|
||||
|
||||
hsa_status_t FindHostRegion(hsa_region_t region, void *data);
|
||||
|
||||
#endif // COMMON_COMMON_HPP
|
||||
@@ -0,0 +1,67 @@
|
||||
#include "common_utility.h"
|
||||
|
||||
|
||||
double CalcMedian(vector<double> scores)
|
||||
{
|
||||
double median;
|
||||
size_t size = scores.size();
|
||||
|
||||
if (size % 2 == 0)
|
||||
median = (scores[size / 2 - 1] + scores[size / 2]) / 2;
|
||||
else
|
||||
median = scores[size / 2];
|
||||
|
||||
return median;
|
||||
}
|
||||
|
||||
double CalcMean(vector<double> scores)
|
||||
{
|
||||
double mean = 0;
|
||||
size_t size = scores.size();
|
||||
|
||||
for (int i=0; i<size; ++i)
|
||||
mean += scores[i];
|
||||
|
||||
return mean/size;
|
||||
}
|
||||
|
||||
|
||||
double CalcStdDeviation(vector<double> scores, int score_mean)
|
||||
{
|
||||
double ret = 0.0;
|
||||
for (int i=0; i<scores.size(); ++i)
|
||||
{
|
||||
ret += (scores[i] - score_mean) * (scores[i] - score_mean);
|
||||
}
|
||||
|
||||
ret /= scores.size();
|
||||
|
||||
return sqrt(ret);
|
||||
}
|
||||
|
||||
int CalcConcurrentQueues(vector<double> scores)
|
||||
{
|
||||
int num_of_concurrent_queues = 0;
|
||||
vector<double>execpted_exec_time_array;
|
||||
|
||||
for (int i=0; i<scores.size(); ++i)
|
||||
{
|
||||
execpted_exec_time_array.push_back(scores[0]/(1<<i));
|
||||
}
|
||||
|
||||
|
||||
for (int i=0; i<scores.size(); ++i)
|
||||
{
|
||||
cout << "expected exe time = " << execpted_exec_time_array[i] << endl;
|
||||
}
|
||||
|
||||
for (int i=1; i<scores.size(); ++i)
|
||||
{
|
||||
if ((execpted_exec_time_array[i] - scores[i]) < 0.1 * execpted_exec_time_array[i])
|
||||
++num_of_concurrent_queues;
|
||||
}
|
||||
|
||||
return num_of_concurrent_queues;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
#include <iostream>
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <vector>
|
||||
using namespace std;
|
||||
|
||||
double CalcMean(vector<double> scores);
|
||||
double CalcMedian(vector<double> scores);
|
||||
double CalcStdDeviation(vector<double> scores, int score_mean);
|
||||
int CalcConcurrentQueues(vector<double> scores);
|
||||
|
||||
|
||||
|
||||
+386
@@ -0,0 +1,386 @@
|
||||
/**********************************************************************
|
||||
Copyright ©2013 Advanced Micro Devices, Inc. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
• Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
• Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
********************************************************************/
|
||||
|
||||
#include "helper_funcs.hpp"
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Prints no more than 256 elements of the given array.
|
||||
* Prints full array if length is less than 256.
|
||||
* Prints Array name followed by elements.
|
||||
*/
|
||||
template<typename T>
|
||||
void printArray(
|
||||
const std::string header,
|
||||
const T * data,
|
||||
const int width,
|
||||
const int height)
|
||||
{
|
||||
std::cout<<"\n"<<header<<"\n";
|
||||
for(int i = 0; i < height; i++)
|
||||
{
|
||||
for(int j = 0; j < width; j++)
|
||||
{
|
||||
std::cout<<data[i*width+j]<<" ";
|
||||
}
|
||||
std::cout<<"\n";
|
||||
}
|
||||
std::cout<<"\n";
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
int fillRandom(
|
||||
T * arrayPtr,
|
||||
const int width,
|
||||
const int height,
|
||||
const T rangeMin,
|
||||
const T rangeMax,
|
||||
unsigned int seed)
|
||||
{
|
||||
if(!arrayPtr)
|
||||
{
|
||||
error("Cannot fill array. NULL pointer.");
|
||||
return HSA_SDK_FAILURE;
|
||||
}
|
||||
|
||||
if(!seed)
|
||||
seed = (unsigned int)time(NULL);
|
||||
|
||||
srand(seed);
|
||||
double range = double(rangeMax - rangeMin) + 1.0;
|
||||
|
||||
/* random initialisation of input */
|
||||
for(int i = 0; i < height; i++)
|
||||
for(int j = 0; j < width; j++)
|
||||
{
|
||||
int index = i*width + j;
|
||||
arrayPtr[index] = rangeMin + T(range*rand()/(RAND_MAX + 1.0));
|
||||
}
|
||||
|
||||
return HSA_SDK_SUCCESS;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
int fillPos(
|
||||
T * arrayPtr,
|
||||
const int width,
|
||||
const int height)
|
||||
{
|
||||
if(!arrayPtr)
|
||||
{
|
||||
error("Cannot fill array. NULL pointer.");
|
||||
return HSA_SDK_FAILURE;
|
||||
}
|
||||
|
||||
/* initialisation of input with positions*/
|
||||
for(T i = 0; i < height; i++)
|
||||
for(T j = 0; j < width; j++)
|
||||
{
|
||||
T index = i*width + j;
|
||||
arrayPtr[index] = index;
|
||||
}
|
||||
|
||||
return HSA_SDK_SUCCESS;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
int fillConstant(
|
||||
T * arrayPtr,
|
||||
const int width,
|
||||
const int height,
|
||||
const T val)
|
||||
{
|
||||
if(!arrayPtr)
|
||||
{
|
||||
error("Cannot fill array. NULL pointer.");
|
||||
return HSA_SDK_FAILURE;
|
||||
}
|
||||
|
||||
/* initialisation of input with constant value*/
|
||||
for(int i = 0; i < height; i++)
|
||||
for(int j = 0; j < width; j++)
|
||||
{
|
||||
int index = i*width + j;
|
||||
arrayPtr[index] = val;
|
||||
}
|
||||
|
||||
return HSA_SDK_SUCCESS;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T roundToPowerOf2(T val)
|
||||
{
|
||||
int bytes = sizeof(T);
|
||||
|
||||
val--;
|
||||
for(int i = 0; i < bytes; i++)
|
||||
val |= val >> (1<<i);
|
||||
val++;
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
int isPowerOf2(T val)
|
||||
{
|
||||
long long _val = val;
|
||||
if((_val & (-_val))-_val == 0 && _val != 0)
|
||||
return HSA_SDK_SUCCESS;
|
||||
else
|
||||
return HSA_SDK_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
template<typename T>
|
||||
bool checkVal(
|
||||
T input,
|
||||
T reference,
|
||||
std::string message,
|
||||
bool isAPIerror)
|
||||
{
|
||||
if(input==reference)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
error(message);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<typename T>
|
||||
std::string toString(T t, std::ios_base &(*r)(std::ios_base&))
|
||||
{
|
||||
std::ostringstream output;
|
||||
output << r << t;
|
||||
return output.str();
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
compare(const float *refData, const float *data,
|
||||
const int length, const float epsilon)
|
||||
{
|
||||
float error = 0.0f;
|
||||
float ref = 0.0f;
|
||||
|
||||
for(int i = 1; i < length; ++i)
|
||||
{
|
||||
float diff = refData[i] - data[i];
|
||||
error += diff * diff;
|
||||
ref += refData[i] * refData[i];
|
||||
}
|
||||
|
||||
float normRef =::sqrtf((float) ref);
|
||||
if (::fabs((float) ref) < 1e-7f) {
|
||||
return false;
|
||||
}
|
||||
float normError = ::sqrtf((float) error);
|
||||
error = normError / normRef;
|
||||
|
||||
return error < epsilon;
|
||||
}
|
||||
|
||||
bool
|
||||
compare(const double *refData, const double *data,
|
||||
const int length, const double epsilon)
|
||||
{
|
||||
double error = 0.0;
|
||||
double ref = 0.0;
|
||||
|
||||
for(int i = 1; i < length; ++i)
|
||||
{
|
||||
double diff = refData[i] - data[i];
|
||||
error += diff * diff;
|
||||
ref += refData[i] * refData[i];
|
||||
}
|
||||
|
||||
double normRef =::sqrt((double) ref);
|
||||
if (::fabs((double) ref) < 1e-7) {
|
||||
return false;
|
||||
}
|
||||
double normError = ::sqrt((double) error);
|
||||
error = normError / normRef;
|
||||
|
||||
return error < epsilon;
|
||||
}
|
||||
|
||||
void
|
||||
error(const char* errorMsg)
|
||||
{
|
||||
std::cout<<"Error: "<<errorMsg<<std::endl;
|
||||
}
|
||||
|
||||
void
|
||||
error(std::string errorMsg)
|
||||
{
|
||||
std::cout<<"Error: "<<errorMsg<<std::endl;
|
||||
}
|
||||
|
||||
void
|
||||
expectedError(const char* errorMsg)
|
||||
{
|
||||
std::cout<<"Expected Error: "<<errorMsg<<std::endl;
|
||||
}
|
||||
|
||||
void
|
||||
expectedError(std::string errorMsg)
|
||||
{
|
||||
std::cout<<"Expected Error: "<<errorMsg<<std::endl;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// Template Instantiations
|
||||
/////////////////////////////////////////////////////////////////
|
||||
template
|
||||
void printArray<short>(const std::string,
|
||||
const short*, int, int);
|
||||
template
|
||||
void printArray<unsigned char>(const std::string,
|
||||
const unsigned char *, int, int);
|
||||
template
|
||||
void printArray<unsigned int>(const std::string,
|
||||
const unsigned int *, int, int);
|
||||
template
|
||||
void printArray<int>(const std::string,
|
||||
const int *, int, int);
|
||||
template
|
||||
void printArray<long>(const std::string,
|
||||
const long*, int, int);
|
||||
template
|
||||
void printArray<float>(const std::string,
|
||||
const float*, int, int);
|
||||
template
|
||||
void printArray<double>(const std::string,
|
||||
const double*, int, int);
|
||||
|
||||
template
|
||||
int fillRandom<unsigned char>(unsigned char* arrayPtr,
|
||||
const int width, const int height,
|
||||
unsigned char rangeMin, unsigned char rangeMax, unsigned int seed);
|
||||
template
|
||||
int fillRandom<unsigned int>(unsigned int* arrayPtr,
|
||||
const int width, const int height,
|
||||
unsigned int rangeMin, unsigned int rangeMax, unsigned int seed);
|
||||
template
|
||||
int fillRandom<int>(int* arrayPtr,
|
||||
const int width, const int height,
|
||||
int rangeMin, int rangeMax, unsigned int seed);
|
||||
template
|
||||
int fillRandom<long>(long* arrayPtr,
|
||||
const int width, const int height,
|
||||
long rangeMin, long rangeMax, unsigned int seed);
|
||||
template
|
||||
int fillRandom<float>(float* arrayPtr,
|
||||
const int width, const int height,
|
||||
float rangeMin, float rangeMax, unsigned int seed);
|
||||
template
|
||||
int fillRandom<double>(double* arrayPtr,
|
||||
const int width, const int height,
|
||||
double rangeMin, double rangeMax, unsigned int seed);
|
||||
|
||||
template
|
||||
short roundToPowerOf2<short>(short val);
|
||||
template
|
||||
unsigned int roundToPowerOf2<unsigned int>(unsigned int val);
|
||||
template
|
||||
int roundToPowerOf2<int>(int val);
|
||||
template
|
||||
long roundToPowerOf2<long>(long val);
|
||||
|
||||
template
|
||||
int isPowerOf2<short>(short val);
|
||||
template
|
||||
int isPowerOf2<unsigned int>(unsigned int val);
|
||||
template
|
||||
int isPowerOf2<int>(int val);
|
||||
template
|
||||
int isPowerOf2<long>(long val);
|
||||
|
||||
template<>
|
||||
int fillPos<short>(short * arrayPtr, const int width, const int height);
|
||||
template<>
|
||||
int fillPos<unsigned int>(unsigned int * arrayPtr, const int width, const int height);
|
||||
template<>
|
||||
int fillPos<int>(int * arrayPtr, const int width, const int height);
|
||||
template<>
|
||||
int fillPos<long>(long * arrayPtr, const int width, const int height);
|
||||
|
||||
template<>
|
||||
int fillConstant<short>(short * arrayPtr,
|
||||
const int width, const int height,
|
||||
const short val);
|
||||
template<>
|
||||
int fillConstant(unsigned int * arrayPtr,
|
||||
const int width, const int height,
|
||||
const unsigned int val);
|
||||
template<>
|
||||
int fillConstant(int * arrayPtr,
|
||||
const int width, const int height,
|
||||
const int val);
|
||||
template<>
|
||||
int fillConstant(long * arrayPtr,
|
||||
const int width, const int height,
|
||||
const long val);
|
||||
template<>
|
||||
int fillConstant(long * arrayPtr,
|
||||
const int width, const int height,
|
||||
const long val);
|
||||
template<>
|
||||
int fillConstant(long * arrayPtr,
|
||||
const int width, const int height,
|
||||
const long val);
|
||||
|
||||
|
||||
template
|
||||
bool checkVal<char>(char input, char reference, std::string message, bool isAPIerror);
|
||||
template
|
||||
bool checkVal<bool>(bool input, bool reference, std::string message, bool isAPIerror);
|
||||
template
|
||||
bool checkVal<std::string>(std::string input, std::string reference, std::string message, bool isAPIerror);
|
||||
template
|
||||
bool checkVal<short>(short input, short reference, std::string message, bool isAPIerror);
|
||||
template
|
||||
bool checkVal<unsigned int>(unsigned int input, unsigned int reference, std::string message, bool isAPIerror);
|
||||
template
|
||||
bool checkVal<int>(int input, int reference, std::string message, bool isAPIerror);
|
||||
template
|
||||
bool checkVal<long>(long input, long reference, std::string message, bool isAPIerror);
|
||||
|
||||
|
||||
template
|
||||
std::string toString<char>(char t, std::ios_base &(*r)(std::ios_base&));
|
||||
template
|
||||
std::string toString<short>(short t, std::ios_base &(*r)(std::ios_base&));
|
||||
template
|
||||
std::string toString<unsigned int>(unsigned int t, std::ios_base &(*r)(std::ios_base&));
|
||||
template
|
||||
std::string toString<int>(int t, std::ios_base &(*r)(std::ios_base&));
|
||||
template
|
||||
std::string toString<long>(long t, std::ios_base &(*r)(std::ios_base&));
|
||||
template
|
||||
std::string toString<float>(float t, std::ios_base &(*r)(std::ios_base&));
|
||||
template
|
||||
std::string toString<double>(double t, std::ios_base &(*r)(std::ios_base&));
|
||||
|
||||
+159
@@ -0,0 +1,159 @@
|
||||
/**********************************************************************
|
||||
Copyright ©2013 Advanced Micro Devices, Inc. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
• Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
• Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
********************************************************************/
|
||||
#ifndef HELPER_FUNCS_HPP_
|
||||
#define HELPER_FUNCS_HPP_
|
||||
|
||||
#define HSA_SDK_SUCCESS 0
|
||||
#define HSA_SDK_FAILURE 1
|
||||
#define HSA_SDK_EXPECTED_FAILURE 2
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <iomanip>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <ctime>
|
||||
#include <cmath>
|
||||
#include <time.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <vector>
|
||||
#include <malloc.h>
|
||||
|
||||
/**
|
||||
* error
|
||||
* constant function, Prints error messages
|
||||
* @param errorMsg char* message
|
||||
*/
|
||||
void error(const char* errorMsg);
|
||||
|
||||
/**
|
||||
* error
|
||||
* constant function, Prints error messages
|
||||
* @param errorMsg std::string message
|
||||
*/
|
||||
void error(std::string errorMsg);
|
||||
|
||||
/**
|
||||
* expectedError
|
||||
* constant function, Prints error messages
|
||||
* @param errorMsg char* message
|
||||
*/
|
||||
void expectedError(const char* errorMsg);
|
||||
|
||||
/**
|
||||
* expectedError
|
||||
* constant function, Prints error messages
|
||||
* @param errorMsg string message
|
||||
*/
|
||||
void expectedError(std::string errorMsg);
|
||||
|
||||
/**
|
||||
* compare template version
|
||||
* compare data to check error
|
||||
* @param refData templated input
|
||||
* @param data templated input
|
||||
* @param length number of values to compare
|
||||
* @param epsilon errorWindow
|
||||
*/
|
||||
bool compare(const float *refData, const float *data,
|
||||
const int length, const float epsilon = 1e-6f);
|
||||
bool compare(const double *refData, const double *data,
|
||||
const int length, const double epsilon = 1e-6);
|
||||
|
||||
/**
|
||||
* printArray
|
||||
* displays a array on std::out
|
||||
*/
|
||||
template<typename T>
|
||||
void printArray(
|
||||
const std::string header,
|
||||
const T * data,
|
||||
const int width,
|
||||
const int height);
|
||||
|
||||
|
||||
/**
|
||||
* fillRandom
|
||||
* fill array with random values
|
||||
*/
|
||||
template<typename T>
|
||||
int fillRandom(
|
||||
T * arrayPtr,
|
||||
const int width,
|
||||
const int height,
|
||||
const T rangeMin,
|
||||
const T rangeMax,
|
||||
unsigned int seed=123);
|
||||
|
||||
/**
|
||||
* fillPos
|
||||
* fill the specified positions
|
||||
*/
|
||||
template<typename T>
|
||||
int fillPos(
|
||||
T * arrayPtr,
|
||||
const int width,
|
||||
const int height);
|
||||
|
||||
/**
|
||||
* fillConstant
|
||||
* fill the array with constant value
|
||||
*/
|
||||
template<typename T>
|
||||
int fillConstant(
|
||||
T * arrayPtr,
|
||||
const int width,
|
||||
const int height,
|
||||
const T val);
|
||||
|
||||
|
||||
/**
|
||||
* roundToPowerOf2
|
||||
* rounds to a power of 2
|
||||
*/
|
||||
template<typename T>
|
||||
T roundToPowerOf2(T val);
|
||||
|
||||
/**
|
||||
* isPowerOf2
|
||||
* checks if input is a power of 2
|
||||
*/
|
||||
template<typename T>
|
||||
int isPowerOf2(T val);
|
||||
|
||||
/**
|
||||
* checkVal
|
||||
* Set default(isAPIerror) parameter to false
|
||||
* if checkVaul is used to check otherthan OpenCL API error code
|
||||
*/
|
||||
template<typename T>
|
||||
bool checkVal(
|
||||
T input,
|
||||
T reference,
|
||||
std::string message, bool isAPIerror = true);
|
||||
|
||||
/**
|
||||
* toString
|
||||
* convert a T type to string
|
||||
*/
|
||||
template<typename T>
|
||||
std::string toString(T t, std::ios_base & (*r)(std::ios_base&));
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,318 @@
|
||||
#include "hsa_base_util.h"
|
||||
#include "HSAILAmdExt.h"
|
||||
|
||||
|
||||
void HSA_UTIL::GetHsailNameAndKernelName(char * file_name_full, char *file_name_base, char *kernel_name)
|
||||
{
|
||||
strcpy(hail_file_name_full, file_name_full);
|
||||
strcpy(hail_file_name_base, file_name_base);
|
||||
strcpy(hsa_kernel_name, kernel_name);
|
||||
}
|
||||
|
||||
HSA_UTIL::HSA_UTIL()
|
||||
{
|
||||
#ifdef TIME
|
||||
base_kernel_time_idx = base_timer.CreateTimer();
|
||||
base_setup_time_idx = base_timer.CreateTimer();
|
||||
#endif
|
||||
}
|
||||
|
||||
HSA_UTIL::~HSA_UTIL()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
bool HSA_UTIL::HsaInit()
|
||||
{
|
||||
#ifdef TIME
|
||||
base_timer.StartTimer(base_setup_time_idx);
|
||||
#endif
|
||||
|
||||
err = hsa_init();
|
||||
check(Initializing the hsa runtime, err);
|
||||
|
||||
/*
|
||||
* Iterate over the agents and pick the gpu agent using
|
||||
* the find_gpu callback.
|
||||
*/
|
||||
err = hsa_iterate_agents(find_gpu, &device);
|
||||
check(Calling hsa_iterate_agents, err);
|
||||
|
||||
err = (device.handle== 0) ? HSA_STATUS_ERROR : HSA_STATUS_SUCCESS;
|
||||
check(Checking if the GPU device is non-zero, err);
|
||||
|
||||
if (err == HSA_STATUS_ERROR)
|
||||
return false;
|
||||
|
||||
/*
|
||||
* Query the maximum size of the queue.
|
||||
*/
|
||||
err = hsa_agent_get_info(device, HSA_AGENT_INFO_QUEUE_MAX_SIZE, &queue_size);
|
||||
check(Querying the device maximum queue size, err);
|
||||
|
||||
/*
|
||||
* Create a queue using the maximum size.
|
||||
*/
|
||||
err = hsa_queue_create(device, queue_size, HSA_QUEUE_TYPE_MULTI, NULL, NULL, 0, 0, &command_queue);
|
||||
check(Creating the queue, err);
|
||||
|
||||
profile = hsa_profile_t(108);
|
||||
hsa_agent_get_info(device, HSA_AGENT_INFO_PROFILE, &profile);
|
||||
|
||||
if (profile == HSA_PROFILE_BASE)
|
||||
{
|
||||
memset(hail_file_name_full, 0, sizeof(char)*128);
|
||||
cout << "Loading base profile!!!" << endl;
|
||||
strcpy(hail_file_name_full, hail_file_name_base); //overwrite full hsail file name with base
|
||||
}
|
||||
|
||||
amd::hsail::registerExtensions();
|
||||
if (!tool.assembleFromFile(hail_file_name_full))
|
||||
{
|
||||
std::cout << tool.output();
|
||||
return false;
|
||||
}
|
||||
module = tool.brigModule();
|
||||
|
||||
// Create hsail program.
|
||||
err = hsa_ext_program_create(HSA_MACHINE_MODEL_LARGE, profile, HSA_DEFAULT_FLOAT_ROUNDING_MODE_ZERO, NULL, &hsa_program);
|
||||
check("Error in creating program object", err);
|
||||
|
||||
// Add hsail module.
|
||||
//cout << "hsail file name = " << hail_file_name_full << endl;
|
||||
err = hsa_ext_program_add_module(hsa_program, module);
|
||||
check("Error in adding module to program object", err);
|
||||
|
||||
// Finalize hsail program.
|
||||
hsa_isa_t isa = {0};
|
||||
err = hsa_agent_get_info(device, HSA_AGENT_INFO_ISA, &isa);
|
||||
check("Get hsa agent info isa", err);
|
||||
|
||||
hsa_ext_control_directives_t control_directives;
|
||||
memset(&control_directives, 0, sizeof(hsa_ext_control_directives_t));
|
||||
|
||||
err = hsa_ext_program_finalize(hsa_program,
|
||||
isa,
|
||||
0,
|
||||
control_directives,
|
||||
NULL, //"-g -O0 -dump-isa",
|
||||
HSA_CODE_OBJECT_TYPE_PROGRAM,
|
||||
&code_object);
|
||||
check("Error in finalizing program object", err);
|
||||
|
||||
// Create executable.
|
||||
err = hsa_executable_create(profile, HSA_EXECUTABLE_STATE_UNFROZEN, "", &hsaExecutable);
|
||||
check("Error in creating executable object", err);
|
||||
|
||||
// Load code object.
|
||||
err = hsa_executable_load_code_object(hsaExecutable, device, code_object, "");
|
||||
check("Error in loading executable object", err);
|
||||
|
||||
// Freeze executable.
|
||||
err = hsa_executable_freeze(hsaExecutable, "");
|
||||
check("Error in freezing executable object", err);
|
||||
|
||||
// Get symbol handle.
|
||||
err = hsa_executable_get_symbol(hsaExecutable, NULL, hsa_kernel_name, device, 0, &kernelSymbol);
|
||||
check("get symbol handle", err);
|
||||
|
||||
// Get code handle.
|
||||
|
||||
err = hsa_executable_symbol_get_info(kernelSymbol, HSA_EXECUTABLE_SYMBOL_INFO_KERNEL_OBJECT, &codeHandle);
|
||||
check("Get code handle", err);
|
||||
|
||||
#ifdef TIME
|
||||
base_timer.StopTimer(base_setup_time_idx);
|
||||
#endif
|
||||
|
||||
|
||||
//hsa_region_t local_kernarg_region;
|
||||
mem_region.kernarg_region.handle = 0;
|
||||
mem_region.coarse_region.handle = 0;
|
||||
|
||||
hsa_agent_iterate_regions(device, get_memory_region, &mem_region);
|
||||
err = (mem_region.kernarg_region.handle== 0) ? HSA_STATUS_ERROR : HSA_STATUS_SUCCESS;
|
||||
check(Finding a kernarg memory region, err);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
double HSA_UTIL::Run(int dim, int group_x, int group_y, int group_z, int s_size, int grid_x, int grid_y, int grid_z, void* kernel_args, int kernel_args_size)
|
||||
{
|
||||
#ifdef TIME
|
||||
base_timer.StartTimer(base_kernel_time_idx);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Create a signal to wait for the dispatch to finish.
|
||||
*/
|
||||
hsa_signal_t local_signal;
|
||||
err=hsa_signal_create(1, 0, NULL, &local_signal);
|
||||
check(Creating a HSA_UTIL signal, err);
|
||||
|
||||
/* Initialize the dispatch packet */
|
||||
hsa_kernel_dispatch_packet_t local_dispatch_packet;
|
||||
memset(&local_dispatch_packet, 0, sizeof(hsa_kernel_dispatch_packet_t));
|
||||
/*
|
||||
* Setup the dispatch information.
|
||||
*/
|
||||
local_dispatch_packet.completion_signal=local_signal;
|
||||
local_dispatch_packet.setup |= dim<< HSA_KERNEL_DISPATCH_PACKET_SETUP_DIMENSIONS;
|
||||
local_dispatch_packet.workgroup_size_x = group_x;
|
||||
local_dispatch_packet.workgroup_size_y = group_y;
|
||||
local_dispatch_packet.workgroup_size_z = group_z;
|
||||
local_dispatch_packet.group_segment_size = s_size;
|
||||
local_dispatch_packet.grid_size_x = grid_x;
|
||||
local_dispatch_packet.grid_size_y = grid_y;
|
||||
local_dispatch_packet.grid_size_z = grid_z;
|
||||
local_dispatch_packet.header |= HSA_PACKET_TYPE_KERNEL_DISPATCH;
|
||||
//local_dispatch_packet.header |= HSA_FENCE_SCOPE_AGENT << HSA_PACKET_HEADER_ACQUIRE_FENCE_SCOPE;
|
||||
//local_dispatch_packet.header |= HSA_FENCE_SCOPE_AGENT << HSA_PACKET_HEADER_RELEASE_FENCE_SCOPE;
|
||||
local_dispatch_packet.header |= HSA_FENCE_SCOPE_SYSTEM << HSA_PACKET_HEADER_ACQUIRE_FENCE_SCOPE;
|
||||
local_dispatch_packet.header |= HSA_FENCE_SCOPE_SYSTEM << HSA_PACKET_HEADER_RELEASE_FENCE_SCOPE;
|
||||
local_dispatch_packet.kernel_object = codeHandle;
|
||||
|
||||
// Specify amount of private segment size (in bytes) that is needed per work-item
|
||||
// Retrieve the amount of private memory needed
|
||||
uint32_t private_mem_size = 0;
|
||||
hsa_executable_symbol_get_info(kernelSymbol,
|
||||
HSA_EXECUTABLE_SYMBOL_INFO_KERNEL_PRIVATE_SEGMENT_SIZE, &private_mem_size);
|
||||
local_dispatch_packet.private_segment_size = private_mem_size;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/*
|
||||
* Find a memory region that supports kernel arguments.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
kernarg_region.handle = 0;
|
||||
|
||||
hsa_agent_iterate_regions(device, get_kernarg, &kernarg_region);
|
||||
err = (kernarg_region.handle== 0) ? HSA_STATUS_ERROR : HSA_STATUS_SUCCESS;
|
||||
check(Finding a kernarg memory region, err);
|
||||
|
||||
*/
|
||||
|
||||
void* local_kernel_arg_buffer = NULL;
|
||||
/*
|
||||
* Allocate the kernel argument buffer from the correct region.
|
||||
*/
|
||||
err = hsa_memory_allocate(mem_region.kernarg_region, kernel_args_size, &local_kernel_arg_buffer);
|
||||
check(Allocating kernel argument memory buffer, err);
|
||||
memcpy(local_kernel_arg_buffer, kernel_args, kernel_args_size);
|
||||
local_dispatch_packet.kernarg_address = local_kernel_arg_buffer;
|
||||
|
||||
/*
|
||||
* Obtain the current queue write index.
|
||||
*/
|
||||
uint64_t index = hsa_queue_load_write_index_relaxed(command_queue);
|
||||
|
||||
/*
|
||||
* Write the aql packet at the calculated queue index address.
|
||||
*/
|
||||
const uint32_t queueMask = command_queue->size - 1;
|
||||
((hsa_kernel_dispatch_packet_t*)(command_queue->base_address))[index&queueMask]=local_dispatch_packet;
|
||||
|
||||
/*
|
||||
* Increment the write index and ring the doorbell to dispatch the kernel.
|
||||
*/
|
||||
hsa_queue_store_write_index_relaxed(command_queue, index+1);
|
||||
hsa_signal_store_release(command_queue->doorbell_signal, index);
|
||||
|
||||
/*
|
||||
* Wait on the dispatch signal until all kernel are finished.
|
||||
*/
|
||||
while (hsa_signal_wait_acquire(local_signal, HSA_SIGNAL_CONDITION_EQ, 0, UINT64_MAX, HSA_WAIT_STATE_ACTIVE) != 0);
|
||||
|
||||
#ifdef TIME
|
||||
base_timer.StopTimer(base_kernel_time_idx);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Cleanup all allocated resources.
|
||||
*/
|
||||
|
||||
err = hsa_memory_free(local_kernel_arg_buffer);
|
||||
check(Deallocate memory, err);
|
||||
|
||||
err=hsa_signal_destroy(local_signal);
|
||||
check(Destroying the local_signal, err);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
double HSA_UTIL::GetKernelTime()
|
||||
{
|
||||
return base_timer.ReadTimer(base_kernel_time_idx);
|
||||
}
|
||||
|
||||
double HSA_UTIL::GetSetupTime()
|
||||
{
|
||||
return base_timer.ReadTimer(base_setup_time_idx);
|
||||
}
|
||||
|
||||
void HSA_UTIL::Close()
|
||||
{
|
||||
err = hsa_executable_destroy(hsaExecutable);
|
||||
check(Destroying the hsaExecutable, err)
|
||||
|
||||
err = hsa_code_object_destroy(code_object);
|
||||
check(Destroying the code_object, err);
|
||||
|
||||
err=hsa_queue_destroy(command_queue);
|
||||
check(Destroying the queue, err);
|
||||
|
||||
err=hsa_shut_down();
|
||||
check(Shutting down the runtime, err);
|
||||
}
|
||||
|
||||
void* HSA_UTIL::AllocateLocalMemory(size_t size)
|
||||
{
|
||||
void *buffer = NULL;
|
||||
|
||||
// Allocate in local memory only if it is available
|
||||
if (mem_region.coarse_region.handle != 0)
|
||||
{
|
||||
cout << "Allocating in local memory" << endl;
|
||||
err = hsa_memory_allocate(mem_region.coarse_region, size, (void **)&buffer);
|
||||
check(hsa memory allocation in local memory, err);
|
||||
|
||||
// register agent
|
||||
err = hsa_memory_assign_agent(buffer, device, HSA_ACCESS_PERMISSION_RW);
|
||||
return (err == HSA_STATUS_SUCCESS) ? buffer : NULL;
|
||||
}
|
||||
|
||||
// Allocate in system memory if local memory is not available
|
||||
cout << "Allocating in system memory" << endl;
|
||||
err = hsa_memory_allocate(mem_region.kernarg_region, size, (void **)&buffer);
|
||||
return (err == HSA_STATUS_SUCCESS) ? buffer : NULL;
|
||||
}
|
||||
|
||||
void* HSA_UTIL::AllocateSysMemory( size_t size)
|
||||
{
|
||||
void *buffer = NULL;
|
||||
err = hsa_memory_allocate(mem_region.kernarg_region, size, (void **)&buffer);
|
||||
return (err == HSA_STATUS_SUCCESS) ? buffer : NULL;
|
||||
}
|
||||
|
||||
bool HSA_UTIL::TransferData(void *dest, void *src, uint length, bool host_to_dev)
|
||||
{
|
||||
|
||||
hsa_status_t status;
|
||||
|
||||
void *buffer = (host_to_dev) ? dest : src;
|
||||
err = hsa_memory_assign_agent(buffer, device, HSA_ACCESS_PERMISSION_RW);
|
||||
if (err != HSA_STATUS_SUCCESS)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
err = hsa_memory_copy(dest, src, length); // first is dest, second is src
|
||||
return (err == HSA_STATUS_SUCCESS);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
#ifndef __HSA_BASE__
|
||||
#define __HSA_BASE__
|
||||
|
||||
|
||||
#include <vector>
|
||||
#include "hsa.h"
|
||||
#include "hsa_ext_finalize.h"
|
||||
#include "hsa_ext_amd.h"
|
||||
#include "hsatimer.h"
|
||||
#include "utilities.h"
|
||||
#include "common.hpp"
|
||||
#include "HSAILTool.h"
|
||||
|
||||
class HSA_UTIL{
|
||||
public:
|
||||
HSA_UTIL();
|
||||
~HSA_UTIL();
|
||||
|
||||
public:
|
||||
void GetHsailNameAndKernelName(char *hail_file_name_full, char *hail_file_name_base, char *kernel_name);
|
||||
bool HsaInit();
|
||||
void Close();
|
||||
double GetKernelTime();
|
||||
double GetSetupTime();
|
||||
void* AllocateLocalMemory(size_t size) ;
|
||||
void* AllocateSysMemory(size_t size);
|
||||
bool TransferData(void *dest, void *src, uint length, bool host_to_dev) ;
|
||||
|
||||
double Run(int dim, int group_x, int group_y, int group_z, int s_size, int grid_x, int grid_y, int grid_z, void* kernel_args, int kernel_args_size);
|
||||
|
||||
public:
|
||||
hsa_status_t err;
|
||||
uint32_t queue_size;
|
||||
hsa_agent_t device;
|
||||
MemRegion mem_region;
|
||||
//hsa_region_t kernarg_region;
|
||||
// Memory region supporting kernel parameters
|
||||
// hsa_region_t coarse_region;
|
||||
// Hsail profile supported by agent
|
||||
hsa_profile_t profile;
|
||||
|
||||
char hail_file_name_full[128];
|
||||
char hail_file_name_base[128];
|
||||
char hsa_kernel_name[128];
|
||||
|
||||
hsa_queue_t* command_queue;
|
||||
HSAIL_ASM::Tool tool;
|
||||
hsa_ext_module_t module;
|
||||
hsa_ext_program_t hsa_program;
|
||||
hsa_executable_t hsaExecutable;
|
||||
hsa_executable_symbol_t kernelSymbol;
|
||||
hsa_code_object_t code_object;
|
||||
uint64_t codeHandle;
|
||||
hsa_signal_t hsa_signal;
|
||||
hsa_kernel_dispatch_packet_t dispatch_packet;
|
||||
hsa_region_t hsa_kernarg_region;
|
||||
|
||||
PerfTimer base_timer;
|
||||
int base_kernel_time_idx;
|
||||
int base_setup_time_idx;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,184 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <cassert>
|
||||
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "hsa.h"
|
||||
#include "tools/inc/hsa_ext_profiler.h"
|
||||
#include "tools/inc/amd_hsa_tools_interfaces.h"
|
||||
|
||||
#include "hsa_perf_cntrs.hpp"
|
||||
|
||||
using namespace std;
|
||||
|
||||
void PreDispatchCallback(const hsa_dispatch_callback_t* dispParam, void* usrArg) {
|
||||
assert((dispParam->pre_dispatch) && "Pre Dispatch Callback Param is Malformed");
|
||||
|
||||
hsa_ext_tools_pmu_t* perfMgr = reinterpret_cast<hsa_ext_tools_pmu_t*>(usrArg);
|
||||
hsa_status_t status = hsa_ext_tools_pmu_begin(*perfMgr, dispParam->queue,
|
||||
dispParam->aql_translation_handle, true);
|
||||
assert((status == HSA_STATUS_SUCCESS) && "Error in beginning Perf Cntr Session");
|
||||
}
|
||||
|
||||
void PostDispatchCallback(const hsa_dispatch_callback_t* dispParam, void* usrArg) {
|
||||
assert((!dispParam->pre_dispatch) && "Post Dispatch Callback Param is Malformed");
|
||||
|
||||
hsa_ext_tools_pmu_t* perfMgr = reinterpret_cast<hsa_ext_tools_pmu_t*>(usrArg);
|
||||
hsa_status_t status = hsa_ext_tools_pmu_end(*perfMgr, dispParam->queue,
|
||||
dispParam->aql_translation_handle);
|
||||
assert((status == HSA_STATUS_SUCCESS) && "Error in endning Perf Cntr Session");
|
||||
}
|
||||
|
||||
// Constructor of the class
|
||||
RocrPerfCntrApp::RocrPerfCntrApp( ) : perfMgr_(NULL) {
|
||||
|
||||
}
|
||||
|
||||
// Destructor of the class. Ideally it should delete the
|
||||
// PMU and its counters
|
||||
RocrPerfCntrApp::~RocrPerfCntrApp( ) {
|
||||
|
||||
}
|
||||
|
||||
// Return the number of perf counters
|
||||
uint32_t RocrPerfCntrApp::GetNumPerfCntrs( ) {
|
||||
return uint32_t(cntrList_.size());
|
||||
}
|
||||
|
||||
// Return the handle of perf counter at specified index
|
||||
CntrInfo* RocrPerfCntrApp::GetPerfCntr(uint32_t idx) {
|
||||
return cntrList_[idx];
|
||||
}
|
||||
|
||||
// Print the various fields of Perf Cntrs being programmed
|
||||
bool RocrPerfCntrApp::PrintCntrs( ) {
|
||||
|
||||
CntrInfo *info;
|
||||
int size = uint32_t(cntrList_.size());
|
||||
for (int idx = 0; idx < size; idx++) {
|
||||
info = cntrList_[idx];
|
||||
std::cout << std::endl;
|
||||
std::cout << "Rocr Perf Cntr Id: " << info->cntrId << std::endl;
|
||||
std::cout << "Rocr Perf Cntr Name: " << info->cntrName << std::endl;
|
||||
std::cout << "Rocr Perf Cntr Blk Id: " << info->blkId << std::endl;
|
||||
std::cout << "Rocr Perf Cntr Value: " << info->cntrResult << std::endl;
|
||||
std::cout << "Rocr Perf Cntr Validation: " << info->cnfType << std::endl;
|
||||
std::cout << std::endl;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Initialize the list of perf counters
|
||||
// block id of kHsaAiCounterBlockSQ = 14 == 0x0E
|
||||
hsa_status_t RocrPerfCntrApp::Init(hsa_agent_t agent) {
|
||||
|
||||
// Initialize the list of Perf Cntrs
|
||||
// Add SQ counter for number of waves
|
||||
CntrInfo* info = NULL;
|
||||
cntrList_.reserve(23);
|
||||
|
||||
char *cntrChoice = getenv("IOMMU");
|
||||
if (cntrChoice == NULL) {
|
||||
// Event for number of Waves
|
||||
info = new CntrInfo(0x4, "SQ_SQ_PERF_SEL_WAVES", NULL,
|
||||
0x0E, NULL, 0x00, 0xFFFFFFFF, CntrValCnf_Exact);
|
||||
cntrList_.push_back(info);
|
||||
|
||||
// Event for number of Threads
|
||||
info = new CntrInfo(0xE, "SQ_SQ_PERF_SEL_ITEMS", NULL,
|
||||
0x0E, NULL, 0x00, 0xFFFFFFFF, CntrValCnf_Exact);
|
||||
cntrList_.push_back(info);
|
||||
|
||||
} else {
|
||||
|
||||
// Program to collect event number 4
|
||||
info = new CntrInfo(0x4, "Iommu_Cntr_4", NULL,
|
||||
0x63, NULL, 0x00, 0xFFFFFFFF, CntrValCnf_None);
|
||||
cntrList_.push_back(info);
|
||||
|
||||
// Program to collect event number 6
|
||||
info = new CntrInfo(0x6, "Iommu_Cntr_6", NULL,
|
||||
0x63, NULL, 0x00, 0xFFFFFFFF, CntrValCnf_None);
|
||||
cntrList_.push_back(info);
|
||||
}
|
||||
|
||||
|
||||
// Create an instance of Perf Mgr
|
||||
hsa_status_t status;
|
||||
status = hsa_ext_tools_create_pmu(agent, &perfMgr_);
|
||||
assert((status == HSA_STATUS_SUCCESS) && "Error in creating Perf Cntr Mgr");
|
||||
|
||||
// Process each counter from the list as necessary
|
||||
// each counter descriptor with its perf block handle
|
||||
// and create an instance of counter in that block
|
||||
uint32_t size = GetNumPerfCntrs();
|
||||
for (uint32_t idx = 0; idx < size; idx++) {
|
||||
info = GetPerfCntr(idx);
|
||||
|
||||
// Obtain the handle of perf block
|
||||
if (info->blkHndl == NULL) {
|
||||
status = hsa_ext_tools_get_counter_block_by_id(perfMgr_, info->blkId, &info->blkHndl);
|
||||
assert((status == HSA_STATUS_SUCCESS) && "Error in getting Perf Cntr Blk Hndl");
|
||||
}
|
||||
|
||||
// Create an instance of counter in the perf block
|
||||
status = hsa_ext_tools_create_counter(info->blkHndl, &info->cntrHndl);
|
||||
assert((status == HSA_STATUS_SUCCESS) && "Error in creating Perf Cntr in Perf Blk");
|
||||
|
||||
// Update the Event Index property of counter
|
||||
uint32_t cntrProp = HSA_EXT_TOOLS_COUNTER_PARAMETER_EVENT_INDEX;
|
||||
status = hsa_ext_tools_set_counter_parameter(info->cntrHndl, cntrProp,
|
||||
sizeof(uint32_t), (void*)&info->cntrId);
|
||||
assert((status == HSA_STATUS_SUCCESS) && "Error in updating Perf Cntr Property Event Index");
|
||||
|
||||
// Enable the updated perf counter
|
||||
status = hsa_ext_tools_set_counter_enabled(info->cntrHndl, true);
|
||||
assert((status == HSA_STATUS_SUCCESS) && "Error in enabing Perf Cntr");
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
// Register Pre and Post dispatch callbacks
|
||||
void RocrPerfCntrApp::RegisterCallbacks(hsa_queue_t *queue){
|
||||
|
||||
hsa_status_t status;
|
||||
status = hsa_ext_tools_set_callback_functions(queue, PreDispatchCallback, PostDispatchCallback);
|
||||
assert((status == HSA_STATUS_SUCCESS) && "Error in registering Pre & Post Dispatch Callbacks");
|
||||
status = hsa_ext_tools_set_callback_arguments(queue, &perfMgr_, &perfMgr_);
|
||||
assert((status == HSA_STATUS_SUCCESS) && "Error in registering Pre & Post Dispatch Callback Params");
|
||||
return;
|
||||
}
|
||||
|
||||
// Wait for perf counter collection to complete
|
||||
hsa_status_t RocrPerfCntrApp::Wait() {
|
||||
|
||||
hsa_status_t status;
|
||||
status = hsa_ext_tools_pmu_wait_for_completion(perfMgr_, 5000);
|
||||
assert((status == HSA_STATUS_SUCCESS) && "Error in Waiting for Perf Cntr Completion");
|
||||
return status;
|
||||
}
|
||||
|
||||
// Validate perf counter values
|
||||
hsa_status_t RocrPerfCntrApp::Validate() {
|
||||
|
||||
// Retrieve the results of the different Perf Cntrs
|
||||
// and validate them as configured
|
||||
CntrInfo* info = NULL;
|
||||
hsa_status_t status = HSA_STATUS_SUCCESS;
|
||||
uint32_t size = GetNumPerfCntrs();
|
||||
for (uint32_t idx = 0; idx < size; idx++) {
|
||||
info = GetPerfCntr(idx);
|
||||
status = hsa_ext_tools_get_counter_result(info->cntrHndl, &info->cntrResult);
|
||||
std::cout << "Value of Perf Cntr is: " << info->cntrResult << std::endl;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
#ifndef ROCR_PERF_CNTR_APP_H_
|
||||
#define ROCR_PERF_CNTR_APP_H_
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
#include "hsa.h"
|
||||
#include "tools/inc/hsa_ext_profiler.h"
|
||||
|
||||
typedef enum CntrValCnfType {
|
||||
|
||||
///< no counter value validation should be performed
|
||||
CntrValCnf_None,
|
||||
|
||||
///< counter value should be an exact match to expectedResult
|
||||
CntrValCnf_Exact,
|
||||
|
||||
///< counter value should be greater than expectedResult
|
||||
CntrValCnf_GreaterThan,
|
||||
|
||||
///< counter value should be less than expectedResult
|
||||
CntrValCnf_LessThan
|
||||
|
||||
} CntrValCnfType;
|
||||
|
||||
/// Struct used to encapsulate Counter Info
|
||||
typedef struct CntrInfo {
|
||||
|
||||
///< Id of counter in hardware block
|
||||
uint32_t cntrId;
|
||||
|
||||
///< Name of counter
|
||||
char cntrName[72];
|
||||
|
||||
///< Handle of perf counter
|
||||
hsa_ext_tools_counter_t cntrHndl;
|
||||
|
||||
///< Id of hardware block containing the counter
|
||||
uint32_t blkId;
|
||||
|
||||
///< Handle of counter block
|
||||
hsa_ext_tools_counter_block_t blkHndl;
|
||||
|
||||
///< Expected value of perf counte
|
||||
uint64_t expectedResult;
|
||||
|
||||
///< Value of perf counter expected
|
||||
uint64_t cntrResult;
|
||||
|
||||
///< Type of validation upon completion of dispatch
|
||||
CntrValCnfType cnfType;
|
||||
|
||||
CntrInfo(uint32_t cntrId, char* cntrName, void* cntrHndl,
|
||||
uint32_t blkId, void* blkHndl,
|
||||
uint64_t expResult, uint64_t result, CntrValCnfType cnfType) {
|
||||
this->cntrId = cntrId;
|
||||
this->cntrHndl = cntrHndl;
|
||||
this->blkId = blkId;
|
||||
this->blkHndl = blkHndl;
|
||||
this->expectedResult = expResult;
|
||||
this->cntrResult = result;
|
||||
this->cnfType = cnfType;
|
||||
memcpy(this->cntrName, cntrName, strlen(cntrName));
|
||||
}
|
||||
|
||||
} CntrInfo;
|
||||
|
||||
class RocrPerfCntrApp {
|
||||
|
||||
public:
|
||||
|
||||
// Constructor of the class. Will initialize the list of perf counters
|
||||
// that will be used to program the device
|
||||
RocrPerfCntrApp( );
|
||||
|
||||
// Destructor of the class
|
||||
~RocrPerfCntrApp( );
|
||||
|
||||
// Return the number of perf counters
|
||||
uint32_t GetNumPerfCntrs();
|
||||
|
||||
// Return the handle of perf counter at specified index
|
||||
CntrInfo* GetPerfCntr(uint32_t idx);
|
||||
|
||||
// Print the list of perf counters
|
||||
bool PrintCntrs();
|
||||
|
||||
// Initialize the list of perf counters
|
||||
hsa_status_t Init(hsa_agent_t agent);
|
||||
|
||||
// Register Pre and Post dispatch callbacks
|
||||
void RegisterCallbacks(hsa_queue_t *queue);
|
||||
|
||||
// Wait for perf counter collection to complete
|
||||
hsa_status_t Wait();
|
||||
|
||||
// Validate perf counter values
|
||||
hsa_status_t Validate();
|
||||
|
||||
private:
|
||||
|
||||
// Number of queues to create
|
||||
std::vector<CntrInfo *> cntrList_;
|
||||
|
||||
// Handle of Perf Cntr Manager
|
||||
hsa_ext_tools_pmu_t perfMgr_;
|
||||
};
|
||||
|
||||
#endif // ROCR_PERF_CNTR_APP_H_
|
||||
+582
@@ -0,0 +1,582 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <cassert>
|
||||
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
#include "hsa.h"
|
||||
#include "hsa_rsrc_factory.hpp"
|
||||
#include "hsa_ext_finalize.h"
|
||||
#include "tools/inc/hsa_ext_profiler.h"
|
||||
#include "HSAILAmdExt.h"
|
||||
|
||||
#include "common.hpp"
|
||||
|
||||
using namespace std;
|
||||
|
||||
// Provide access to command line arguments passed in by user
|
||||
uint32_t hsa_cmdline_arg_cnt;
|
||||
char **hsa_cmdline_arg_list;
|
||||
|
||||
// Callback function to find and bind kernarg region of an agent
|
||||
static hsa_status_t find_memregions(hsa_region_t region, void *data) {
|
||||
|
||||
hsa_region_global_flag_t flags;
|
||||
hsa_region_segment_t segment_id;
|
||||
|
||||
hsa_region_get_info(region, HSA_REGION_INFO_SEGMENT, &segment_id);
|
||||
if (segment_id != HSA_REGION_SEGMENT_GLOBAL) {
|
||||
return HSA_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
AgentInfo *agent_info = (AgentInfo *)data;
|
||||
hsa_region_get_info(region, HSA_REGION_INFO_GLOBAL_FLAGS, &flags);
|
||||
if (flags & HSA_REGION_GLOBAL_FLAG_COARSE_GRAINED) {
|
||||
agent_info->coarse_region = region;
|
||||
}
|
||||
|
||||
if (flags & HSA_REGION_GLOBAL_FLAG_KERNARG) {
|
||||
agent_info->kernarg_region = region;
|
||||
}
|
||||
|
||||
return HSA_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Callback function to get the number of agents
|
||||
static hsa_status_t get_hsa_agents(hsa_agent_t agent, void *data) {
|
||||
|
||||
// Copy handle of agent and increment number of agents reported
|
||||
HsaRsrcFactory *rsrcFactory = reinterpret_cast<HsaRsrcFactory *>(data);
|
||||
|
||||
// Determine if device is a Gpu agent
|
||||
hsa_status_t status;
|
||||
hsa_device_type_t type;
|
||||
status = hsa_agent_get_info(agent, HSA_AGENT_INFO_DEVICE, &type);
|
||||
if (type == HSA_DEVICE_TYPE_DSP) {
|
||||
return HSA_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
if (type == HSA_DEVICE_TYPE_CPU) {
|
||||
AgentInfo *agent_info = reinterpret_cast<AgentInfo *>(malloc(sizeof(AgentInfo)));
|
||||
agent_info->dev_id = agent;
|
||||
agent_info->dev_type = HSA_DEVICE_TYPE_CPU;
|
||||
rsrcFactory->AddAgentInfo(agent_info, false);
|
||||
return HSA_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Device is a Gpu agent, build an instance of AgentInfo
|
||||
AgentInfo *agent_info = reinterpret_cast<AgentInfo *>(malloc(sizeof(AgentInfo)));
|
||||
agent_info->dev_id = agent;
|
||||
agent_info->dev_type = HSA_DEVICE_TYPE_GPU;
|
||||
hsa_agent_get_info(agent, HSA_AGENT_INFO_NAME, agent_info->name);
|
||||
agent_info->max_wave_size = 0;
|
||||
hsa_agent_get_info(agent, HSA_AGENT_INFO_WAVEFRONT_SIZE, &agent_info->max_wave_size);
|
||||
agent_info->max_queue_size = 0;
|
||||
hsa_agent_get_info(agent, HSA_AGENT_INFO_QUEUE_MAX_SIZE, &agent_info->max_queue_size);
|
||||
agent_info->profile = hsa_profile_t(108);
|
||||
hsa_agent_get_info(agent, HSA_AGENT_INFO_PROFILE, &agent_info->profile);
|
||||
|
||||
// Initialize memory regions to zero
|
||||
agent_info->kernarg_region.handle = 0;
|
||||
agent_info->coarse_region.handle = 0;
|
||||
|
||||
// Find and Bind Memory regions of the Gpu agent
|
||||
hsa_agent_iterate_regions(agent, find_memregions, agent_info);
|
||||
|
||||
// Save the instance of AgentInfo
|
||||
rsrcFactory->AddAgentInfo(agent_info, true);
|
||||
return HSA_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Definitions for Static Data members of the class
|
||||
char* HsaRsrcFactory::brig_path_ = NULL;
|
||||
uint32_t HsaRsrcFactory::num_cus_;
|
||||
uint32_t HsaRsrcFactory::num_waves_;
|
||||
uint32_t HsaRsrcFactory::num_workitems_;
|
||||
uint32_t HsaRsrcFactory::kernel_loop_count_;
|
||||
bool HsaRsrcFactory::print_debug_info_ = false;
|
||||
|
||||
char* HsaRsrcFactory::num_cus_key_ = "num_cus";
|
||||
char* HsaRsrcFactory::brig_path_key_ = "brig_path";
|
||||
char* HsaRsrcFactory::num_waves_key_ = "waves_per_cu";
|
||||
char* HsaRsrcFactory::num_workitems_key_ = "workitems_per_wave";
|
||||
char* HsaRsrcFactory::print_debug_key_ = "print_debug";
|
||||
char* HsaRsrcFactory::kernel_loop_count_key_ = "kernel_loop_count";
|
||||
|
||||
// Constructor of the class
|
||||
HsaRsrcFactory::HsaRsrcFactory( ) {
|
||||
|
||||
// Initialize the Hsa Runtime
|
||||
hsa_status_t status = hsa_init();
|
||||
assert(status == HSA_STATUS_SUCCESS);
|
||||
|
||||
// Discover the set of Gpu devices available on the platform
|
||||
status = hsa_iterate_agents(get_hsa_agents, this);
|
||||
check("Error Calling hsa_iterate_agents", status);
|
||||
|
||||
// Process command line arguments
|
||||
ProcessCmdline( );
|
||||
}
|
||||
|
||||
// Destructor of the class
|
||||
HsaRsrcFactory::~HsaRsrcFactory( ) {
|
||||
|
||||
}
|
||||
|
||||
// Get the count of Hsa Gpu Agents available on the platform
|
||||
//
|
||||
// @return uint32_t Number of Gpu agents on platform
|
||||
//
|
||||
uint32_t HsaRsrcFactory::GetCountOfGpuAgents( ) {
|
||||
return uint32_t(gpu_list_.size());
|
||||
}
|
||||
|
||||
// Get the count of Hsa Cpu Agents available on the platform
|
||||
//
|
||||
// @return uint32_t Number of Cpu agents on platform
|
||||
//
|
||||
uint32_t HsaRsrcFactory::GetCountOfCpuAgents( ) {
|
||||
return uint32_t(cpu_list_.size());
|
||||
}
|
||||
|
||||
// Get the AgentInfo handle of a Gpu device
|
||||
//
|
||||
// @param idx Gpu Agent at specified index
|
||||
//
|
||||
// @param agent_info Output parameter updated with AgentInfo
|
||||
//
|
||||
// @return bool true if successful, false otherwise
|
||||
//
|
||||
bool HsaRsrcFactory::GetGpuAgentInfo(uint32_t idx, AgentInfo **agent_info) {
|
||||
|
||||
// Determine if request is valid
|
||||
uint32_t size = uint32_t(gpu_list_.size());
|
||||
if (idx >= size) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Copy AgentInfo from specified index
|
||||
*agent_info = gpu_list_[idx];
|
||||
return true;
|
||||
}
|
||||
|
||||
// Get the AgentInfo handle of a Cpu device
|
||||
//
|
||||
// @param idx Cpu Agent at specified index
|
||||
//
|
||||
// @param agent_info Output parameter updated with AgentInfo
|
||||
//
|
||||
// @return bool true if successful, false otherwise
|
||||
//
|
||||
bool HsaRsrcFactory::GetCpuAgentInfo(uint32_t idx, AgentInfo **agent_info) {
|
||||
|
||||
// Determine if request is valid
|
||||
uint32_t size = uint32_t(cpu_list_.size());
|
||||
if (idx >= size) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Copy AgentInfo from specified index
|
||||
*agent_info = cpu_list_[idx];
|
||||
return true;
|
||||
}
|
||||
|
||||
// Create a Queue object and return its handle. The queue object is expected
|
||||
// to support user requested number of Aql dispatch packets.
|
||||
//
|
||||
// @param agent_info Gpu Agent on which to create a queue object
|
||||
//
|
||||
// @param num_Pkts Number of packets to be held by queue
|
||||
//
|
||||
// @param queue Output parameter updated with handle of queue object
|
||||
//
|
||||
// @return bool true if successful, false otherwise
|
||||
//
|
||||
bool HsaRsrcFactory::CreateQueue(AgentInfo *agent_info,
|
||||
uint32_t num_pkts, hsa_queue_t **queue) {
|
||||
|
||||
hsa_status_t status;
|
||||
|
||||
// Code to create a Profile Queue object
|
||||
if (num_pkts == UINT32_MAX) {
|
||||
status = hsa_ext_tools_queue_create_profiled(agent_info->dev_id,
|
||||
512, HSA_QUEUE_TYPE_SINGLE, NULL,
|
||||
NULL, UINT32_MAX, UINT32_MAX, queue);
|
||||
return (status == HSA_STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
status = hsa_queue_create(agent_info->dev_id, num_pkts,
|
||||
HSA_QUEUE_TYPE_MULTI, NULL, NULL,
|
||||
UINT32_MAX, UINT32_MAX, queue);
|
||||
return (status == HSA_STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
// Create a Signal object and return its handle.
|
||||
//
|
||||
// @param value Initial value of signal object
|
||||
//
|
||||
// @param signal Output parameter updated with handle of signal object
|
||||
//
|
||||
// @return bool true if successful, false otherwise
|
||||
//
|
||||
bool HsaRsrcFactory::CreateSignal(uint32_t value, hsa_signal_t *signal) {
|
||||
|
||||
hsa_status_t status;
|
||||
status = hsa_signal_create(value, 0, NULL, signal);
|
||||
return (status == HSA_STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
// Allocate memory for use by a kernel of specified size in specified
|
||||
// agent's memory region. Currently supports Global segment whose Kernarg
|
||||
// flag set.
|
||||
//
|
||||
// @param agent_info Agent from whose memory region to allocate
|
||||
//
|
||||
// @param size Size of memory in terms of bytes
|
||||
//
|
||||
// @return uint8_t* Pointer to buffer, null if allocation fails.
|
||||
//
|
||||
uint8_t* HsaRsrcFactory::AllocateLocalMemory(AgentInfo *agent_info, size_t size) {
|
||||
|
||||
hsa_status_t status;
|
||||
uint8_t *buffer = NULL;
|
||||
|
||||
// Allocate in local memory only if it is available
|
||||
if (agent_info->coarse_region.handle != 0) {
|
||||
std::cout << "Allocating in local memory" << std::endl;
|
||||
status = hsa_memory_allocate(agent_info->coarse_region, size, (void **)&buffer);
|
||||
if (status == HSA_STATUS_SUCCESS) {
|
||||
status = hsa_memory_assign_agent(buffer, agent_info->dev_id, HSA_ACCESS_PERMISSION_RW);
|
||||
return (status == HSA_STATUS_SUCCESS) ? buffer : NULL;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Allocate in system memory if local memory is not available
|
||||
std::cout << "Allocating in system memory" << std::endl;
|
||||
status = hsa_memory_allocate(agent_info->kernarg_region, size, (void **)&buffer);
|
||||
return (status == HSA_STATUS_SUCCESS) ? buffer : NULL;
|
||||
}
|
||||
|
||||
// Allocate memory tp pass kernel parameters.
|
||||
//
|
||||
// @param agent_info Agent from whose memory region to allocate
|
||||
//
|
||||
// @param size Size of memory in terms of bytes
|
||||
//
|
||||
// @return uint8_t* Pointer to buffer, null if allocation fails.
|
||||
//
|
||||
uint8_t* HsaRsrcFactory::AllocateSysMemory(AgentInfo *agent_info, size_t size) {
|
||||
|
||||
hsa_status_t status;
|
||||
uint8_t *buffer = NULL;
|
||||
status = hsa_memory_allocate(agent_info->kernarg_region, size, (void **)&buffer);
|
||||
return (status == HSA_STATUS_SUCCESS) ? buffer : NULL;
|
||||
}
|
||||
|
||||
bool HsaRsrcFactory::TransferData(uint8_t *dest_buff, uint8_t *src_buff,
|
||||
uint32_t length, bool host_to_dev) {
|
||||
|
||||
hsa_status_t status;
|
||||
status = hsa_memory_copy(dest_buff, src_buff, length);
|
||||
return (status == HSA_STATUS_SUCCESS);
|
||||
|
||||
}
|
||||
|
||||
// Fake method for compilation steps only
|
||||
uint8_t* HsaRsrcFactory::AllocateMemory(AgentInfo *agent_info, size_t size) {
|
||||
|
||||
hsa_status_t status;
|
||||
uint8_t *buffer = NULL;
|
||||
status = hsa_memory_allocate(agent_info->kernarg_region, size, (void **)&buffer);
|
||||
return (status == HSA_STATUS_SUCCESS) ? buffer : NULL;
|
||||
}
|
||||
|
||||
// Loads an Assembled Brig file and Finalizes it into Device Isa
|
||||
//
|
||||
// @param agent_info Gpu device for which to finalize
|
||||
//
|
||||
// @param brig_path File path of the Assembled Brig file
|
||||
//
|
||||
// @param kernel_name Name of the kernel to finalize
|
||||
//
|
||||
// @param code_desc Handle of finalized Code Descriptor that could
|
||||
// be used to submit for execution
|
||||
//
|
||||
// @return bool true if successful, false otherwise
|
||||
//
|
||||
bool HsaRsrcFactory::LoadAndFinalize(AgentInfo *agent_info,
|
||||
const char *brig_path, char *kernel_name,
|
||||
hsa_executable_symbol_t *code_desc) {
|
||||
|
||||
hsa_status_t status;
|
||||
// Load BRIG, encapsulated in an ELF container, into a BRIG module.
|
||||
/*
|
||||
status_t build_err;
|
||||
hsa_ext_brig_module_t *brig_obj;
|
||||
build_err = (status_t)create_brig_module_from_brig_file(brig_path, &brig_obj);
|
||||
check_build("Error in creating the brig module from brig file", build_err);
|
||||
|
||||
// Determine the Brig module has the kernel symbol
|
||||
hsa_status_t status;
|
||||
hsa_ext_brig_code_section_offset32_t kernel_symbol;
|
||||
status = hsa_find_symbol_offset(brig_obj, kernel_name, &kernel_symbol);
|
||||
check("Error in Finding the Symbol Offset for the Kernel", status);
|
||||
*/
|
||||
|
||||
amd::hsail::registerExtensions();
|
||||
|
||||
// Copy handle of Brig object
|
||||
hsa_ext_module_t brig_module_v3;
|
||||
if (!tool.assembleFromFile(brig_path)) {
|
||||
std::cout << tool.output();
|
||||
return false;
|
||||
}
|
||||
brig_module_v3 = tool.brigModule();
|
||||
|
||||
// Create hsail program.
|
||||
hsa_ext_program_t hsailProgram;
|
||||
status = hsa_ext_program_create(HSA_MACHINE_MODEL_LARGE,
|
||||
agent_info->profile,
|
||||
HSA_DEFAULT_FLOAT_ROUNDING_MODE_ZERO,
|
||||
NULL, &hsailProgram);
|
||||
check("Error in creating program object", status);
|
||||
|
||||
// Add hsail module.
|
||||
status = hsa_ext_program_add_module(hsailProgram, brig_module_v3);
|
||||
check("Error in adding module to program object", status);
|
||||
|
||||
// Finalize hsail program.
|
||||
hsa_isa_t isa = {0};
|
||||
status = hsa_agent_get_info(agent_info->dev_id, HSA_AGENT_INFO_ISA, &isa);
|
||||
check("Error in getting Id of Isa supported by agent", status);
|
||||
|
||||
hsa_ext_control_directives_t control_directives;
|
||||
memset(&control_directives, 0, sizeof(hsa_ext_control_directives_t));
|
||||
|
||||
hsa_code_object_t code_object;
|
||||
status = hsa_ext_program_finalize(hsailProgram,
|
||||
isa,
|
||||
0,
|
||||
control_directives,
|
||||
NULL, //"-g -O0 -dump-isa",
|
||||
HSA_CODE_OBJECT_TYPE_PROGRAM,
|
||||
&code_object);
|
||||
check("Error in finalizing program object", status);
|
||||
|
||||
//status = hsa_ext_program_destroy(hsailProgram);
|
||||
//check("Error in destroying program object", status);
|
||||
|
||||
// Create executable.
|
||||
hsa_executable_t hsaExecutable;
|
||||
status = hsa_executable_create(agent_info->profile,
|
||||
HSA_EXECUTABLE_STATE_UNFROZEN,
|
||||
"", &hsaExecutable);
|
||||
check("Error in creating executable object", status);
|
||||
|
||||
// Load code object.
|
||||
status = hsa_executable_load_code_object(hsaExecutable, agent_info->dev_id, code_object, "");
|
||||
check("Error in loading executable object", status);
|
||||
|
||||
// Freeze executable.
|
||||
status = hsa_executable_freeze(hsaExecutable, "");
|
||||
check("Error in freezing executable object", status);
|
||||
|
||||
// Get symbol handle.
|
||||
hsa_executable_symbol_t kernelSymbol;
|
||||
status = hsa_executable_get_symbol(hsaExecutable, NULL,
|
||||
kernel_name, agent_info->dev_id, 0, &kernelSymbol);
|
||||
|
||||
// Update output parameter
|
||||
*code_desc = kernelSymbol;
|
||||
return true;
|
||||
|
||||
/**
|
||||
|
||||
// Create Hsa Program
|
||||
hsa_ext_program_handle_t program;
|
||||
status = hsa_ext_program_create(&agent_info->dev_id, 1,
|
||||
HSA_EXT_BRIG_MACHINE_LARGE,
|
||||
HSA_EXT_BRIG_PROFILE_FULL, &program);
|
||||
check("Error in Creating Hsa Program", status);
|
||||
|
||||
// Add the BRIG module to hsa program.
|
||||
hsa_ext_brig_module_handle_t brig_handle;
|
||||
status = hsa_ext_add_module(program, brig_obj, &brig_handle);
|
||||
check("Error in Adding Brig Module to the Program", status);
|
||||
|
||||
// Construct finalization request list.
|
||||
hsa_ext_finalization_request_t finalize_request;
|
||||
finalize_request.module = brig_handle;
|
||||
finalize_request.symbol = kernel_symbol;
|
||||
finalize_request.program_call_convention = 0;
|
||||
|
||||
// Finalize the Hsa Program.
|
||||
status = hsa_ext_finalize_program(program, agent_info->dev_id,
|
||||
1, &finalize_request, NULL, NULL, 0, NULL, 0);
|
||||
check("Error in Finalizing the Hsa Program", status);
|
||||
|
||||
// Destroy the brig module. The program was successfully created the kernel
|
||||
// symbol was found and the program was finalized, so it is no longer needed.
|
||||
destroy_brig_module(brig_obj);
|
||||
|
||||
// Get the hsa code descriptor address.
|
||||
status = hsa_ext_query_kernel_descriptor_address(program, brig_handle, kernel_symbol, code_desc);
|
||||
check("Error Querying the Kernel Descriptor Address", status);
|
||||
|
||||
return true;
|
||||
**/
|
||||
}
|
||||
|
||||
// Add an instance of AgentInfo representing a Hsa Gpu agent
|
||||
void HsaRsrcFactory::AddAgentInfo(AgentInfo *agent_info, bool gpu) {
|
||||
|
||||
// Add input to Gpu list
|
||||
if (gpu) {
|
||||
gpu_list_.push_back(agent_info);
|
||||
return;
|
||||
}
|
||||
|
||||
// Add input to Cpu list
|
||||
cpu_list_.push_back(agent_info);
|
||||
}
|
||||
|
||||
// Print the various fields of Hsa Gpu Agents
|
||||
bool HsaRsrcFactory::PrintGpuAgents( ) {
|
||||
|
||||
AgentInfo *agent_info;
|
||||
int size = uint32_t(gpu_list_.size());
|
||||
for (int idx = 0; idx < size; idx++) {
|
||||
agent_info = gpu_list_[idx];
|
||||
std::cout << std::endl;
|
||||
std::cout << "Hsa Gpu Agent Id: " << agent_info->dev_id.handle << std::endl;
|
||||
std::cout << "Hsa Gpu Agent Name: " << agent_info->name << std::endl;
|
||||
std::cout << "Hsa Gpu Agent Max Wave Size: " << agent_info->max_wave_size << std::endl;
|
||||
std::cout << "Hsa Gpu Agent Max Queue Size: " << agent_info->max_queue_size << std::endl;
|
||||
std::cout << "Hsa Gpu Agent Kernarg Region Id: " << agent_info->coarse_region.handle << std::endl;
|
||||
std::cout << std::endl;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Returns the file path where brig files is located. Value is
|
||||
// available only after an instance has been built.
|
||||
char* HsaRsrcFactory::GetBrigPath( ) {
|
||||
return HsaRsrcFactory::brig_path_;
|
||||
}
|
||||
|
||||
// Returns the number of compute units present on platform
|
||||
// Value is available only after an instance has been built.
|
||||
uint32_t HsaRsrcFactory::GetNumOfCUs( ) {
|
||||
return HsaRsrcFactory::num_cus_;
|
||||
}
|
||||
|
||||
// Returns the maximum number of waves that can be launched
|
||||
// per compute unit. The actual number that can be launched
|
||||
// is affected by resource availability
|
||||
//
|
||||
// Value is available only after an instance has been built.
|
||||
uint32_t HsaRsrcFactory::GetNumOfWavesPerCU( ) {
|
||||
return HsaRsrcFactory::num_waves_;
|
||||
}
|
||||
|
||||
// Returns the number of work-items that can execute per wave
|
||||
// Value is available only after an instance has been built.
|
||||
uint32_t HsaRsrcFactory::GetNumOfWorkItemsPerWave( ) {
|
||||
return HsaRsrcFactory::num_workitems_;
|
||||
}
|
||||
|
||||
// Returns the number of times kernel loop body should execute.
|
||||
// Value is available only after an instance has been built.
|
||||
uint32_t HsaRsrcFactory::GetKernelLoopCount() {
|
||||
return HsaRsrcFactory::kernel_loop_count_;
|
||||
}
|
||||
|
||||
// Returns boolean flag to indicate if debug info should be printed
|
||||
// Value is available only after an instance has been built.
|
||||
uint32_t HsaRsrcFactory::GetPrintDebugInfo() {
|
||||
return HsaRsrcFactory::print_debug_info_;
|
||||
}
|
||||
|
||||
// Process command line arguments. The method will capture
|
||||
// various user command line parameters for tests to use
|
||||
void HsaRsrcFactory::ProcessCmdline( ) {
|
||||
|
||||
// Command line arguments are given
|
||||
uint32_t idx;
|
||||
uint32_t arg_idx;
|
||||
for (idx = 1; idx < hsa_cmdline_arg_cnt; idx += 2) {
|
||||
arg_idx = GetArgIndex((char *)hsa_cmdline_arg_list[idx]);
|
||||
switch(arg_idx) {
|
||||
case 0:
|
||||
HsaRsrcFactory::brig_path_ = hsa_cmdline_arg_list[idx + 1];
|
||||
break;
|
||||
case 1:
|
||||
HsaRsrcFactory::num_cus_ = atoi(hsa_cmdline_arg_list[idx + 1]);
|
||||
break;
|
||||
case 2:
|
||||
HsaRsrcFactory::num_waves_ = atoi(hsa_cmdline_arg_list[idx + 1]);
|
||||
break;
|
||||
case 3:
|
||||
HsaRsrcFactory::num_workitems_ = atoi(hsa_cmdline_arg_list[idx + 1]);
|
||||
break;
|
||||
case 4:
|
||||
HsaRsrcFactory::kernel_loop_count_ = atoi(hsa_cmdline_arg_list[idx + 1]);
|
||||
break;
|
||||
case 5:
|
||||
HsaRsrcFactory::print_debug_info_ = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
uint32_t HsaRsrcFactory::GetArgIndex(char *arg_value ) {
|
||||
|
||||
// Map Brig file path to index zero
|
||||
if (!strcmp(HsaRsrcFactory::brig_path_key_, arg_value)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Map Number of Compute Units to index one
|
||||
if (!strcmp(HsaRsrcFactory::num_cus_key_, arg_value)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Map Number of Waves per CU to index two
|
||||
if (!strcmp(HsaRsrcFactory::num_waves_key_, arg_value)) {
|
||||
return 2;
|
||||
}
|
||||
|
||||
// Map Number of Workitems per Wave to index three
|
||||
if (!strcmp(HsaRsrcFactory::num_workitems_key_, arg_value)) {
|
||||
return 3;
|
||||
}
|
||||
|
||||
// Map Kernel Loop Count to index four
|
||||
if (!strcmp(HsaRsrcFactory::kernel_loop_count_key_, arg_value)) {
|
||||
return 4;
|
||||
}
|
||||
|
||||
// Map print debug info parameter
|
||||
if (!strcmp(HsaRsrcFactory::print_debug_key_, arg_value)) {
|
||||
return 5;
|
||||
}
|
||||
|
||||
return 108;
|
||||
|
||||
}
|
||||
|
||||
void HsaRsrcFactory::PrintHelpMsg( ) {
|
||||
|
||||
std::cout << "Key for passing Brig filepath: " << HsaRsrcFactory::brig_path_key_ << std::endl;
|
||||
std::cout << "Key for passing Number of Compute Units: " << HsaRsrcFactory::num_cus_key_ << std::endl;
|
||||
std::cout << "Key for passing Number of Waves per CU: " << HsaRsrcFactory::num_waves_key_ << std::endl;
|
||||
std::cout << "Key for passing Number of Workitems per Wave: " << HsaRsrcFactory::num_workitems_key_ << std::endl;
|
||||
std::cout << "Key for passing Kernel Loop Count: " << HsaRsrcFactory::kernel_loop_count_key_ << std::endl;
|
||||
|
||||
}
|
||||
+322
@@ -0,0 +1,322 @@
|
||||
#ifndef HSA_RSRC_FACTORY_H_
|
||||
#define HSA_RSRC_FACTORY_H_
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
#include "hsatimer.h"
|
||||
#include "hsa.h"
|
||||
#include "hsa_ext_finalize.h"
|
||||
#include "HSAILTool.h"
|
||||
|
||||
|
||||
#define HSA_ARGUMENT_ALIGN_BYTES 16
|
||||
#define HSA_QUEUE_ALIGN_BYTES 64
|
||||
#define HSA_PACKET_ALIGN_BYTES 64
|
||||
|
||||
#define check(msg, status) \
|
||||
if (status != HSA_STATUS_SUCCESS) { \
|
||||
const char *emsg = 0; \
|
||||
hsa_status_string(status, &emsg); \
|
||||
printf("%s: %s\n", msg, emsg ? emsg : "<unknown error>"); \
|
||||
exit(1); \
|
||||
}
|
||||
|
||||
#define check_build(msg, status) \
|
||||
if (status != STATUS_SUCCESS) { \
|
||||
printf("%s\n", msg); \
|
||||
exit(1); \
|
||||
}
|
||||
|
||||
// Define required BRIG data structures.
|
||||
typedef uint32_t BrigCodeOffset32_t;
|
||||
typedef uint32_t BrigDataOffset32_t;
|
||||
typedef uint16_t BrigKinds16_t;
|
||||
typedef uint8_t BrigLinkage8_t;
|
||||
typedef uint8_t BrigExecutableModifier8_t;
|
||||
typedef BrigDataOffset32_t BrigDataOffsetString32_t;
|
||||
|
||||
/*
|
||||
enum BrigKinds {
|
||||
BRIG_KIND_NONE = 0x0000,
|
||||
BRIG_KIND_DIRECTIVE_BEGIN = 0x1000,
|
||||
BRIG_KIND_DIRECTIVE_KERNEL = 0x1008,
|
||||
};
|
||||
|
||||
typedef struct BrigBase BrigBase;
|
||||
struct BrigBase {
|
||||
uint16_t byteCount;
|
||||
BrigKinds16_t kind;
|
||||
};
|
||||
|
||||
typedef struct BrigExecutableModifier BrigExecutableModifier;
|
||||
struct BrigExecutableModifier {
|
||||
BrigExecutableModifier8_t allBits;
|
||||
};
|
||||
|
||||
typedef struct BrigDirectiveExecutable BrigDirectiveExecutable;
|
||||
struct BrigDirectiveExecutable {
|
||||
uint16_t byteCount;
|
||||
BrigKinds16_t kind;
|
||||
BrigDataOffsetString32_t name;
|
||||
uint16_t outArgCount;
|
||||
uint16_t inArgCount;
|
||||
BrigCodeOffset32_t firstInArg;
|
||||
BrigCodeOffset32_t firstCodeBlockEntry;
|
||||
BrigCodeOffset32_t nextModuleEntry;
|
||||
uint32_t codeBlockEntryCount;
|
||||
BrigExecutableModifier modifier;
|
||||
BrigLinkage8_t linkage;
|
||||
uint16_t reserved;
|
||||
};
|
||||
|
||||
typedef struct BrigData BrigData;
|
||||
struct BrigData {
|
||||
uint32_t byteCount;
|
||||
uint8_t bytes[1];
|
||||
};
|
||||
*/
|
||||
|
||||
// Provide access to command line arguments passed in by user
|
||||
extern uint32_t hsa_cmdline_arg_cnt;
|
||||
extern char **hsa_cmdline_arg_list;
|
||||
|
||||
// Encapsulates information about a Hsa Agent such as its
|
||||
// handle, name, max queue size, max wavefront size, etc.
|
||||
typedef struct {
|
||||
|
||||
// Handle of Agent
|
||||
hsa_agent_t dev_id;
|
||||
|
||||
// Agent type - Cpu = 0, Gpu = 1 or Dsp = 2
|
||||
uint32_t dev_type;
|
||||
|
||||
// Name of Agent whose length is less than 64
|
||||
char name[64];
|
||||
|
||||
// Max size of Wavefront size
|
||||
uint32_t max_wave_size;
|
||||
|
||||
// Max size of Queue buffer
|
||||
uint32_t max_queue_size;
|
||||
|
||||
// Hsail profile supported by agent
|
||||
hsa_profile_t profile;
|
||||
|
||||
// Memory region supporting kernel parameters
|
||||
hsa_region_t coarse_region;
|
||||
|
||||
// Memory region supporting kernel arguments
|
||||
hsa_region_t kernarg_region;
|
||||
|
||||
} AgentInfo;
|
||||
|
||||
class HsaRsrcFactory {
|
||||
|
||||
public:
|
||||
|
||||
// Constructor of the class. Will initialize the Hsa Runtime and
|
||||
// query the system topology to get the list of Cpu and Gpu devices
|
||||
HsaRsrcFactory( );
|
||||
|
||||
// Destructor of the class
|
||||
~HsaRsrcFactory( );
|
||||
|
||||
// Get the count of Hsa Gpu Agents available on the platform
|
||||
//
|
||||
// @return uint32_t Number of Gpu agents on platform
|
||||
//
|
||||
uint32_t GetCountOfGpuAgents( );
|
||||
|
||||
// Get the count of Hsa Cpu Agents available on the platform
|
||||
//
|
||||
// @return uint32_t Number of Cpu agents on platform
|
||||
//
|
||||
uint32_t GetCountOfCpuAgents( );
|
||||
|
||||
// Get the AgentInfo handle of a Gpu device
|
||||
//
|
||||
// @param idx Gpu Agent at specified index
|
||||
//
|
||||
// @param agent_info Output parameter updated with AgentInfo
|
||||
//
|
||||
// @return bool true if successful, false otherwise
|
||||
//
|
||||
bool GetGpuAgentInfo(uint32_t idx, AgentInfo **agent_info);
|
||||
|
||||
// Get the AgentInfo handle of a Cpu device
|
||||
//
|
||||
// @param idx Cpu Agent at specified index
|
||||
//
|
||||
// @param agent_info Output parameter updated with AgentInfo
|
||||
//
|
||||
// @return bool true if successful, false otherwise
|
||||
//
|
||||
bool GetCpuAgentInfo(uint32_t idx, AgentInfo **agent_info);
|
||||
|
||||
// Create a Queue object and return its handle. The queue object is expected
|
||||
// to support user requested number of Aql dispatch packets.
|
||||
//
|
||||
// @param agent_info Gpu Agent on which to create a queue object
|
||||
//
|
||||
// @param num_Pkts Number of packets to be held by queue
|
||||
//
|
||||
// @param queue Output parameter updated with handle of queue object
|
||||
//
|
||||
// @return bool true if successful, false otherwise
|
||||
//
|
||||
bool CreateQueue(AgentInfo *agent_info,
|
||||
uint32_t num_pkts, hsa_queue_t **queue);
|
||||
|
||||
// Create a Signal object and return its handle.
|
||||
//
|
||||
// @param value Initial value of signal object
|
||||
//
|
||||
// @param signal Output parameter updated with handle of signal object
|
||||
//
|
||||
// @return bool true if successful, false otherwise
|
||||
//
|
||||
bool CreateSignal(uint32_t value, hsa_signal_t *signal);
|
||||
|
||||
// Allocate memory for use by a kernel of specified size in specified
|
||||
// agent's memory region. Currently supports Global segment whose Kernarg
|
||||
// flag set.
|
||||
//
|
||||
// @param agent_info Agent from whose memory region to allocate
|
||||
//
|
||||
// @param size Size of memory in terms of bytes
|
||||
//
|
||||
// @return uint8_t* Pointer to buffer, null if allocation fails.
|
||||
//
|
||||
uint8_t* AllocateLocalMemory(AgentInfo *agent_info, size_t size);
|
||||
uint8_t* AllocateMemory(AgentInfo *agent_info, size_t size);
|
||||
|
||||
bool TransferData(uint8_t *dest_buff, uint8_t *src_buff,
|
||||
uint32_t length, bool host_to_dev);
|
||||
|
||||
// Allocate memory tp pass kernel parameters.
|
||||
//
|
||||
// @param agent_info Agent from whose memory region to allocate
|
||||
//
|
||||
// @param size Size of memory in terms of bytes
|
||||
//
|
||||
// @return uint8_t* Pointer to buffer, null if allocation fails.
|
||||
//
|
||||
uint8_t* AllocateSysMemory(AgentInfo *agent_info, size_t size);
|
||||
|
||||
// Loads an Assembled Brig file and Finalizes it into Device Isa
|
||||
//
|
||||
// @param agent_info Gpu device for which to finalize
|
||||
//
|
||||
// @param brig_path File path of the Assembled Brig file
|
||||
//
|
||||
// @param kernel_name Name of the kernel to finalize
|
||||
//
|
||||
// @param code_desc Handle of finalized Code Descriptor that could
|
||||
// be used to submit for execution
|
||||
//
|
||||
// @return bool true if successful, false otherwise
|
||||
//
|
||||
bool LoadAndFinalize(AgentInfo *agent_info,
|
||||
const char *brig_path, char *kernel_name,
|
||||
hsa_executable_symbol_t *code_desc);
|
||||
|
||||
// Add an instance of AgentInfo representing a Hsa Gpu agent
|
||||
void AddAgentInfo(AgentInfo *agent_info, bool gpu);
|
||||
|
||||
// Returns the file path where brig files is located
|
||||
static char* GetBrigPath( );
|
||||
|
||||
// Returns the number of compute units present on platform
|
||||
static uint32_t GetNumOfCUs( );
|
||||
|
||||
// Returns the maximum number of waves that can be launched
|
||||
// per compute unit. The actual number that can be launched
|
||||
// is affected by resource availability
|
||||
static uint32_t GetNumOfWavesPerCU( );
|
||||
|
||||
// Returns the number of work-items that can execute per wave
|
||||
static uint32_t GetNumOfWorkItemsPerWave( );
|
||||
|
||||
// Returns the number of times kernel loop body should execute.
|
||||
static uint32_t GetKernelLoopCount();
|
||||
|
||||
// Returns boolean flag to indicate if debug info should be printed
|
||||
static uint32_t GetPrintDebugInfo();
|
||||
|
||||
private:
|
||||
|
||||
// Number of queues to create
|
||||
uint32_t num_queues_;
|
||||
|
||||
// Used to maintain a list of Hsa Queue handles
|
||||
std::vector<hsa_queue_t *> queue_list_;
|
||||
|
||||
// Number of Signals to create
|
||||
uint32_t num_signals_;
|
||||
|
||||
// Used to maintain a list of Hsa Signal handles
|
||||
std::vector<hsa_signal_t *> signal_list_;
|
||||
|
||||
// Number of agents reported by platform
|
||||
uint32_t num_agents_;
|
||||
|
||||
// Used to maintain a list of Hsa Gpu Agent Info
|
||||
std::vector<AgentInfo *> gpu_list_;
|
||||
|
||||
// Used to maintain a list of Hsa Cpu Agent Info
|
||||
std::vector<AgentInfo *> cpu_list_;
|
||||
|
||||
// Records the file path where Brig file is located.
|
||||
// Value is available only after an instance has been built.
|
||||
static char* brig_path_;
|
||||
static char* brig_path_key_;
|
||||
|
||||
// Records the number of Compute units present on system.
|
||||
// Value is available only after an instance has been built.
|
||||
static uint32_t num_cus_;
|
||||
static char* num_cus_key_;
|
||||
|
||||
// Records the number of waves that can be launched per Compute unit
|
||||
// Value is available only after an instance has been built.
|
||||
static uint32_t num_waves_;
|
||||
static char* num_waves_key_;
|
||||
|
||||
// Records the number of work-items that can be packed into a wave
|
||||
// Value is available only after an instance has been built.
|
||||
static uint32_t num_workitems_;
|
||||
static char* num_workitems_key_;
|
||||
|
||||
// Records the number of times kernel loop body should run. Value
|
||||
// is available only after an instance has been built.
|
||||
static uint32_t kernel_loop_count_;
|
||||
static char* kernel_loop_count_key_;
|
||||
|
||||
// Records the number of times kernel loop body should run. Value
|
||||
// is available only after an instance has been built.
|
||||
static bool print_debug_info_;
|
||||
static char* print_debug_key_;
|
||||
|
||||
// Print the various fields of Hsa Gpu Agents
|
||||
bool PrintGpuAgents( );
|
||||
|
||||
// Process command line arguments. The method will capture
|
||||
// various user command line parameters for tests to use
|
||||
static void ProcessCmdline( );
|
||||
|
||||
// Prints the help banner on user arg keys
|
||||
static void PrintHelpMsg( );
|
||||
|
||||
// Maps an index for the user argument
|
||||
static uint32_t GetArgIndex(char *arg_value);
|
||||
|
||||
HSAIL_ASM::Tool tool;
|
||||
};
|
||||
|
||||
#endif // HSA_RSRC_FACTORY_H_
|
||||
@@ -0,0 +1,516 @@
|
||||
#include "hsa_test.h"
|
||||
|
||||
#include <atomic>
|
||||
#include <iostream>
|
||||
|
||||
#define PRINT_ATTRIBUTE(attribute, value, metric) \
|
||||
std::cout << #attribute " = " << value << " " << metric << std::endl;
|
||||
|
||||
static size_t ToMB(size_t size) { return (size / (1024 * 1024)); }
|
||||
|
||||
HsaTest::HsaTest(const char* test_name) : test_name_(test_name) {
|
||||
std::cout << "Running " << test_name_ << std::endl;
|
||||
std::cout << "------------------------------------------------\n";
|
||||
}
|
||||
|
||||
HsaTest::~HsaTest() {}
|
||||
|
||||
void HsaTest::Init() {
|
||||
hsa_status_t stat = hsa_init();
|
||||
if (stat != HSA_STATUS_SUCCESS) {
|
||||
std::cerr << "hsa_init fail with status " << stat << std::endl;
|
||||
}
|
||||
|
||||
stat = hsa_iterate_agents(IterateAgents, (void*)this);
|
||||
}
|
||||
|
||||
void HsaTest::Cleanup() { hsa_shut_down(); }
|
||||
|
||||
hsa_status_t HsaTest::IterateAgents(hsa_agent_t agent, void* data) {
|
||||
HsaTest* hsatest = (HsaTest*)data;
|
||||
|
||||
AgentProps prop(agent);
|
||||
|
||||
if (prop.device_type == HSA_DEVICE_TYPE_CPU) {
|
||||
hsatest->cpus_.push_back(agent);
|
||||
} else if (prop.device_type == HSA_DEVICE_TYPE_GPU) {
|
||||
hsatest->gpus_.push_back(agent);
|
||||
}
|
||||
|
||||
hsa_amd_memory_pool_t pools[3] = {{0}, {0}, {0}};
|
||||
hsa_status_t stat =
|
||||
hsa_amd_agent_iterate_memory_pools(agent, IteratePools, pools);
|
||||
|
||||
hsatest->global_fine_[agent.handle] = pools[0];
|
||||
hsatest->global_coarse_[agent.handle] = pools[1];
|
||||
hsatest->group_[agent.handle] = pools[2];
|
||||
|
||||
return HSA_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
hsa_status_t HsaTest::IteratePools(hsa_amd_memory_pool_t pool, void* data) {
|
||||
hsa_amd_memory_pool_t* pools = (hsa_amd_memory_pool_t*)data;
|
||||
|
||||
PoolProps prop(pool);
|
||||
|
||||
if (prop.segment == HSA_AMD_SEGMENT_GLOBAL) {
|
||||
if (prop.global_flag & HSA_AMD_MEMORY_POOL_GLOBAL_FLAG_FINE_GRAINED) {
|
||||
pools[0].handle = pool.handle;
|
||||
} else {
|
||||
pools[1].handle = pool.handle;
|
||||
}
|
||||
} else if (prop.segment == HSA_AMD_SEGMENT_GROUP) {
|
||||
pools[2].handle = pool.handle;
|
||||
}
|
||||
|
||||
return HSA_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
HsaTest::AgentProps::AgentProps(hsa_agent_t agent) {
|
||||
if (agent.handle == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
hsa_agent_get_info(agent, HSA_AGENT_INFO_NAME, (void*)name);
|
||||
hsa_agent_get_info(agent, HSA_AGENT_INFO_VENDOR_NAME, (void*)vendor_name);
|
||||
hsa_agent_get_info(agent, HSA_AGENT_INFO_FEATURE, (void*)&feature);
|
||||
hsa_agent_get_info(agent, HSA_AGENT_INFO_MACHINE_MODEL,
|
||||
(void*)&machine_model);
|
||||
hsa_agent_get_info(agent, HSA_AGENT_INFO_PROFILE, (void*)&profile);
|
||||
hsa_agent_get_info(agent, HSA_AGENT_INFO_DEFAULT_FLOAT_ROUNDING_MODE,
|
||||
(void*)&default_float_rounding_mode);
|
||||
hsa_agent_get_info(agent,
|
||||
HSA_AGENT_INFO_BASE_PROFILE_DEFAULT_FLOAT_ROUNDING_MODES,
|
||||
(void*)&base_profile_float_rounding_mode);
|
||||
hsa_agent_get_info(agent, HSA_AGENT_INFO_FAST_F16_OPERATION,
|
||||
(void*)&fast_f16_operation);
|
||||
hsa_agent_get_info(agent, HSA_AGENT_INFO_WAVEFRONT_SIZE,
|
||||
(void*)&wavefront_size);
|
||||
hsa_agent_get_info(agent, HSA_AGENT_INFO_WORKGROUP_MAX_DIM,
|
||||
(void*)workgroup_max_dim);
|
||||
hsa_agent_get_info(agent, HSA_AGENT_INFO_WORKGROUP_MAX_SIZE,
|
||||
(void*)&workgroup_max_size);
|
||||
hsa_agent_get_info(agent, HSA_AGENT_INFO_GRID_MAX_DIM, (void*)&grid_max_dim);
|
||||
hsa_agent_get_info(agent, HSA_AGENT_INFO_GRID_MAX_SIZE,
|
||||
(void*)&grid_max_size);
|
||||
hsa_agent_get_info(agent, HSA_AGENT_INFO_FBARRIER_MAX_SIZE,
|
||||
(void*)&fbarrier_max_size);
|
||||
hsa_agent_get_info(agent, HSA_AGENT_INFO_QUEUES_MAX, (void*)&queue_max);
|
||||
hsa_agent_get_info(agent, HSA_AGENT_INFO_QUEUE_MIN_SIZE,
|
||||
(void*)&queue_min_size);
|
||||
hsa_agent_get_info(agent, HSA_AGENT_INFO_QUEUE_MAX_SIZE,
|
||||
(void*)&queue_max_size);
|
||||
hsa_agent_get_info(agent, HSA_AGENT_INFO_QUEUE_TYPE, (void*)&queue_type);
|
||||
hsa_agent_get_info(agent, HSA_AGENT_INFO_NODE, (void*)&node);
|
||||
hsa_agent_get_info(agent, HSA_AGENT_INFO_DEVICE, (void*)&device_type);
|
||||
hsa_agent_get_info(agent, HSA_AGENT_INFO_CACHE_SIZE, (void*)cache_size);
|
||||
hsa_agent_get_info(agent, HSA_AGENT_INFO_ISA, (void*)&isa);
|
||||
hsa_agent_get_info(agent, HSA_AGENT_INFO_EXTENSIONS, (void*)extensions);
|
||||
hsa_agent_get_info(agent, HSA_AGENT_INFO_VERSION_MAJOR,
|
||||
(void*)&version_major);
|
||||
hsa_agent_get_info(agent, HSA_AGENT_INFO_VERSION_MINOR,
|
||||
(void*)&version_minor);
|
||||
}
|
||||
|
||||
HsaTest::PoolProps::PoolProps(hsa_amd_memory_pool_t pool) {
|
||||
if (pool.handle == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
hsa_amd_memory_pool_get_info(pool, HSA_AMD_MEMORY_POOL_INFO_SEGMENT,
|
||||
(void*)&segment);
|
||||
hsa_amd_memory_pool_get_info(pool, HSA_AMD_MEMORY_POOL_INFO_GLOBAL_FLAGS,
|
||||
(void*)&global_flag);
|
||||
hsa_amd_memory_pool_get_info(pool, HSA_AMD_MEMORY_POOL_INFO_SIZE,
|
||||
(void*)&size);
|
||||
hsa_amd_memory_pool_get_info(pool,
|
||||
HSA_AMD_MEMORY_POOL_INFO_RUNTIME_ALLOC_ALLOWED,
|
||||
(void*)&alloc_allowed);
|
||||
hsa_amd_memory_pool_get_info(pool,
|
||||
HSA_AMD_MEMORY_POOL_INFO_RUNTIME_ALLOC_GRANULE,
|
||||
(void*)&alloc_granule);
|
||||
hsa_amd_memory_pool_get_info(pool,
|
||||
HSA_AMD_MEMORY_POOL_INFO_RUNTIME_ALLOC_ALIGNMENT,
|
||||
(void*)&alloc_alignment);
|
||||
hsa_amd_memory_pool_get_info(pool, HSA_AMD_MEMORY_POOL_INFO_ACCESSIBLE_BY_ALL,
|
||||
(void*)&all_accessible);
|
||||
}
|
||||
|
||||
HsaTest::Kernel::Kernel(hsa_agent_t agent, std::string hsail_text)
|
||||
: agent_(agent), hsail_file_(hsail_text) {
|
||||
program_.handle = 0;
|
||||
code_object_.handle = 0;
|
||||
executable_.handle = 0;
|
||||
|
||||
AgentProps prop(agent_);
|
||||
profile_ = prop.profile;
|
||||
|
||||
Initialize();
|
||||
}
|
||||
|
||||
HsaTest::Kernel::~Kernel() { Cleanup(); }
|
||||
|
||||
uint64_t HsaTest::Kernel::GetCodeHandle(const char* kernel_name) {
|
||||
kernel_symbol_ = {0};
|
||||
if (HSA_STATUS_SUCCESS != hsa_executable_get_symbol(executable_, NULL,
|
||||
kernel_name, agent_, 0,
|
||||
&kernel_symbol_)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint64_t code_handle = 0;
|
||||
if (HSA_STATUS_SUCCESS !=
|
||||
hsa_executable_symbol_get_info(kernel_symbol_,
|
||||
HSA_EXECUTABLE_SYMBOL_INFO_KERNEL_OBJECT,
|
||||
&code_handle)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return code_handle;
|
||||
}
|
||||
|
||||
hsa_status_t HsaTest::Kernel::GetScratchSize(uint32_t* size) {
|
||||
|
||||
hsa_status_t status;
|
||||
status = hsa_executable_symbol_get_info(kernel_symbol_,
|
||||
HSA_EXECUTABLE_SYMBOL_INFO_KERNEL_PRIVATE_SEGMENT_SIZE, size);
|
||||
return status;
|
||||
}
|
||||
|
||||
void HsaTest::Kernel::Initialize() {
|
||||
CreateProgramFromHsailFile();
|
||||
CreateCodeObjectAndExecutable();
|
||||
}
|
||||
|
||||
void HsaTest::Kernel::Cleanup() {
|
||||
if (executable_.handle != 0) {
|
||||
hsa_executable_destroy(executable_);
|
||||
executable_.handle = 0;
|
||||
}
|
||||
|
||||
if (code_object_.handle != 0) {
|
||||
hsa_code_object_destroy(code_object_);
|
||||
code_object_.handle = 0;
|
||||
}
|
||||
|
||||
if (program_.handle != 0) {
|
||||
hsa_ext_program_destroy(program_);
|
||||
program_.handle = 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool HsaTest::Kernel::CreateProgramFromHsailFile() {
|
||||
if (HSA_STATUS_SUCCESS !=
|
||||
hsa_ext_program_create(HSA_MACHINE_MODEL_LARGE, profile_,
|
||||
HSA_DEFAULT_FLOAT_ROUNDING_MODE_ZERO, NULL,
|
||||
&program_)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!tool_.assembleFromFile(hsail_file_.c_str())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
hsa_ext_module_t module = tool_.brigModule();
|
||||
if (HSA_STATUS_SUCCESS != hsa_ext_program_add_module(program_, module)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HsaTest::Kernel::CreateCodeObjectAndExecutable() {
|
||||
hsa_isa_t isa = {0};
|
||||
if (HSA_STATUS_SUCCESS !=
|
||||
hsa_agent_get_info(agent_, HSA_AGENT_INFO_ISA, &isa)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
hsa_ext_control_directives_t control_directives = {0};
|
||||
if (HSA_STATUS_SUCCESS !=
|
||||
hsa_ext_program_finalize(program_, isa, 0, control_directives, "",
|
||||
HSA_CODE_OBJECT_TYPE_PROGRAM, &code_object_)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (HSA_STATUS_SUCCESS != hsa_executable_create(profile_,
|
||||
HSA_EXECUTABLE_STATE_UNFROZEN,
|
||||
"", &executable_)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (HSA_STATUS_SUCCESS !=
|
||||
hsa_executable_load_code_object(executable_, agent_, code_object_, "")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (HSA_STATUS_SUCCESS != hsa_executable_freeze(executable_, "")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void HsaTest::GetGpuPeer(hsa_agent_t master,
|
||||
std::vector<hsa_agent_t>& gpu_peers) {
|
||||
AgentProps master_prop(master);
|
||||
for (hsa_agent_t agent : gpus_) {
|
||||
AgentProps agent_prop(agent);
|
||||
if (master.handle == agent.handle ||
|
||||
agent_prop.device_type != HSA_DEVICE_TYPE_GPU) {
|
||||
continue;
|
||||
}
|
||||
|
||||
hsa_amd_memory_pool_t peer_local_pool = global_coarse_[agent.handle];
|
||||
|
||||
hsa_amd_memory_pool_access_t access =
|
||||
HSA_AMD_MEMORY_POOL_ACCESS_NEVER_ALLOWED;
|
||||
if (HSA_STATUS_SUCCESS == hsa_amd_agent_memory_pool_get_info(
|
||||
master, peer_local_pool,
|
||||
HSA_AMD_AGENT_MEMORY_POOL_INFO_ACCESS,
|
||||
(void*)&access) &&
|
||||
access != HSA_AMD_MEMORY_POOL_ACCESS_NEVER_ALLOWED) {
|
||||
gpu_peers.push_back(agent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void* HsaTest::AllocateSystemMemory(bool fine_grain, size_t size) {
|
||||
if (cpus_.size() == 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
hsa_amd_memory_pool_t pool = (fine_grain) ? global_fine_[cpus_[0].handle]
|
||||
: global_coarse_[cpus_[0].handle];
|
||||
|
||||
void* ptr = NULL;
|
||||
if (HSA_STATUS_SUCCESS != hsa_amd_memory_pool_allocate(pool, size, 0, &ptr)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void* HsaTest::AllocateLocalMemory(hsa_agent_t agent, size_t size) {
|
||||
if (gpus_.size() == 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
hsa_amd_memory_pool_t pool = global_coarse_[agent.handle];
|
||||
|
||||
void* ptr = NULL;
|
||||
if (HSA_STATUS_SUCCESS != hsa_amd_memory_pool_allocate(pool, size, 0, &ptr)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void HsaTest::FreeMemory(void* ptr) { hsa_amd_memory_pool_free(ptr); }
|
||||
|
||||
void HsaTest::LaunchPacket(hsa_queue_t& queue, hsa_packet_type_t type,
|
||||
void* packet) {
|
||||
uint32_t queue_bitmask = queue.size - 1;
|
||||
const uint64_t write_index = hsa_queue_add_write_index_acq_rel(&queue, 1);
|
||||
|
||||
static const uint16_t kInvalidPacketHeader = HSA_PACKET_TYPE_INVALID;
|
||||
|
||||
if (type == HSA_PACKET_TYPE_KERNEL_DISPATCH) {
|
||||
hsa_kernel_dispatch_packet_t* dispatch_packet =
|
||||
reinterpret_cast<hsa_kernel_dispatch_packet_t*>(packet);
|
||||
const uint16_t temp_header = dispatch_packet->header;
|
||||
dispatch_packet->header = kInvalidPacketHeader;
|
||||
|
||||
// Populate queue buffer.
|
||||
hsa_kernel_dispatch_packet_t* queue_buffer =
|
||||
reinterpret_cast<hsa_kernel_dispatch_packet_t*>(queue.base_address);
|
||||
queue_buffer[write_index & queue_bitmask] = *dispatch_packet;
|
||||
|
||||
// Enable packet.
|
||||
std::atomic_thread_fence(std::memory_order_release);
|
||||
queue_buffer[write_index & queue_bitmask].header = temp_header;
|
||||
dispatch_packet->header = temp_header;
|
||||
} else if (type == HSA_PACKET_TYPE_BARRIER_AND) {
|
||||
hsa_barrier_and_packet_t* barrier_and_packet =
|
||||
reinterpret_cast<hsa_barrier_and_packet_t*>(packet);
|
||||
const uint16_t temp_header = barrier_and_packet->header;
|
||||
barrier_and_packet->header = kInvalidPacketHeader;
|
||||
|
||||
// Populate queue buffer.
|
||||
hsa_barrier_and_packet_t* queue_buffer =
|
||||
reinterpret_cast<hsa_barrier_and_packet_t*>(queue.base_address);
|
||||
queue_buffer[write_index & queue_bitmask] = *barrier_and_packet;
|
||||
|
||||
// Enable packet.
|
||||
std::atomic_thread_fence(std::memory_order_release);
|
||||
queue_buffer[write_index & queue_bitmask].header = temp_header;
|
||||
barrier_and_packet->header = temp_header;
|
||||
} else if (type == HSA_PACKET_TYPE_BARRIER_OR) {
|
||||
hsa_barrier_or_packet_t* barrier_or_packet =
|
||||
reinterpret_cast<hsa_barrier_or_packet_t*>(packet);
|
||||
const uint16_t temp_header = barrier_or_packet->header;
|
||||
barrier_or_packet->header = kInvalidPacketHeader;
|
||||
|
||||
// Populate queue buffer.
|
||||
hsa_barrier_or_packet_t* queue_buffer =
|
||||
reinterpret_cast<hsa_barrier_or_packet_t*>(queue.base_address);
|
||||
queue_buffer[write_index & queue_bitmask] = *barrier_or_packet;
|
||||
|
||||
// Enable packet.
|
||||
std::atomic_thread_fence(std::memory_order_release);
|
||||
queue_buffer[write_index & queue_bitmask].header = temp_header;
|
||||
barrier_or_packet->header = temp_header;
|
||||
}
|
||||
|
||||
hsa_signal_store_release(queue.doorbell_signal, write_index);
|
||||
}
|
||||
|
||||
void HsaTest::PrintAgentInfo(AgentProps& prop) {
|
||||
PRINT_ATTRIBUTE(HSA_AGENT_INFO_NAME, prop.name, "");
|
||||
|
||||
PRINT_ATTRIBUTE(HSA_AGENT_INFO_VENDOR_NAME, prop.vendor_name, "");
|
||||
|
||||
const char* feature_strings[] = {"NONE", "HSA_AGENT_FEATURE_DISPATCH",
|
||||
"HSA_AGENT_FEATURE_AGENT_DISPATCH"};
|
||||
PRINT_ATTRIBUTE(HSA_AGENT_INFO_FEATURE, feature_strings[prop.feature], "");
|
||||
|
||||
const char* model_strings[] = {"HSA_MACHINE_MODEL_SMALL",
|
||||
"HSA_MACHINE_MODEL_LARGE"};
|
||||
PRINT_ATTRIBUTE(HSA_AGENT_INFO_MACHINE_MODEL,
|
||||
model_strings[prop.machine_model], "");
|
||||
|
||||
const char* profile_strings[] = {"HSA_PROFILE_BASE", "HSA_PROFILE_FULL"};
|
||||
PRINT_ATTRIBUTE(HSA_AGENT_INFO_PROFILE, profile_strings[prop.profile], "");
|
||||
|
||||
const char* default_float_rounding_strings[] = {
|
||||
"HSA_DEFAULT_FLOAT_ROUNDING_MODE_DEFAULT",
|
||||
"HSA_DEFAULT_FLOAT_ROUNDING_MODE_ZERO",
|
||||
"HSA_DEFAULT_FLOAT_ROUNDING_MODE_NEAR"};
|
||||
PRINT_ATTRIBUTE(
|
||||
HSA_AGENT_INFO_DEFAULT_FLOAT_ROUNDING_MODE,
|
||||
default_float_rounding_strings[prop.default_float_rounding_mode], "");
|
||||
PRINT_ATTRIBUTE(
|
||||
HSA_AGENT_INFO_BASE_PROFILE_DEFAULT_FLOAT_ROUNDING_MODES,
|
||||
default_float_rounding_strings[prop.base_profile_float_rounding_mode],
|
||||
"");
|
||||
|
||||
PRINT_ATTRIBUTE(HSA_AGENT_INFO_FAST_F16_OPERATION, prop.fast_f16_operation,
|
||||
"");
|
||||
|
||||
PRINT_ATTRIBUTE(HSA_AGENT_INFO_WAVEFRONT_SIZE, prop.wavefront_size, "");
|
||||
|
||||
PRINT_ATTRIBUTE(HSA_AGENT_INFO_WORKGROUP_MAX_DIM[0],
|
||||
prop.workgroup_max_dim[0], "");
|
||||
PRINT_ATTRIBUTE(HSA_AGENT_INFO_WORKGROUP_MAX_DIM[1],
|
||||
prop.workgroup_max_dim[1], "");
|
||||
PRINT_ATTRIBUTE(HSA_AGENT_INFO_WORKGROUP_MAX_DIM[2],
|
||||
prop.workgroup_max_dim[2], "");
|
||||
|
||||
PRINT_ATTRIBUTE(HSA_AGENT_INFO_WORKGROUP_MAX_SIZE, prop.workgroup_max_size,
|
||||
"");
|
||||
|
||||
PRINT_ATTRIBUTE(HSA_AGENT_INFO_GRID_MAX_DIM.x, prop.grid_max_dim.x, "");
|
||||
PRINT_ATTRIBUTE(HSA_AGENT_INFO_GRID_MAX_DIM.y, prop.grid_max_dim.y, "");
|
||||
PRINT_ATTRIBUTE(HSA_AGENT_INFO_GRID_MAX_DIM.z, prop.grid_max_dim.z, "");
|
||||
|
||||
PRINT_ATTRIBUTE(HSA_AGENT_INFO_GRID_MAX_SIZE, prop.grid_max_size, "");
|
||||
|
||||
PRINT_ATTRIBUTE(HSA_AGENT_INFO_FBARRIER_MAX_SIZE, prop.fbarrier_max_size, "");
|
||||
|
||||
PRINT_ATTRIBUTE(HSA_AGENT_INFO_QUEUES_MAX, prop.queue_max, "");
|
||||
|
||||
PRINT_ATTRIBUTE(HSA_AGENT_INFO_QUEUE_MIN_SIZE, prop.queue_min_size, "");
|
||||
|
||||
PRINT_ATTRIBUTE(HSA_AGENT_INFO_QUEUE_MAX_SIZE, prop.queue_max_size, "");
|
||||
|
||||
const char* queue_type_strings[] = {"HSA_QUEUE_TYPE_MULTI",
|
||||
"HSA_QUEUE_TYPE_SINGLE"};
|
||||
PRINT_ATTRIBUTE(HSA_AGENT_INFO_QUEUE_TYPE,
|
||||
queue_type_strings[prop.queue_type], "");
|
||||
|
||||
PRINT_ATTRIBUTE(HSA_AGENT_INFO_NODE, prop.node, "");
|
||||
|
||||
const char* device_type_strings[] = {
|
||||
"HSA_DEVICE_TYPE_CPU", "HSA_DEVICE_TYPE_GPU", "HSA_DEVICE_TYPE_DSP"};
|
||||
PRINT_ATTRIBUTE(HSA_AGENT_INFO_DEVICE, device_type_strings[prop.device_type],
|
||||
"");
|
||||
|
||||
PRINT_ATTRIBUTE(HSA_AGENT_INFO_CACHE_SIZE[0], prop.cache_size[0], "bytes");
|
||||
PRINT_ATTRIBUTE(HSA_AGENT_INFO_CACHE_SIZE[1], prop.cache_size[1], "bytes");
|
||||
PRINT_ATTRIBUTE(HSA_AGENT_INFO_CACHE_SIZE[2], prop.cache_size[2], "bytes");
|
||||
PRINT_ATTRIBUTE(HSA_AGENT_INFO_CACHE_SIZE[3], prop.cache_size[3], "bytes");
|
||||
|
||||
std::string extensions = "";
|
||||
extensions += (prop.extensions[HSA_EXTENSION_FINALIZER])
|
||||
? "HSA_EXTENSION_FINALIZER | "
|
||||
: "";
|
||||
extensions +=
|
||||
(prop.extensions[HSA_EXTENSION_IMAGES]) ? "HSA_EXTENSION_IMAGES | " : "";
|
||||
extensions += (prop.extensions[HSA_EXTENSION_AMD_PROFILER])
|
||||
? "HSA_EXTENSION_AMD_PROFILER "
|
||||
: "";
|
||||
PRINT_ATTRIBUTE(HSA_AGENT_INFO_EXTENSIONS, extensions, "");
|
||||
|
||||
PRINT_ATTRIBUTE(HSA_AGENT_INFO_VERSION_MAJOR, prop.version_major, "");
|
||||
PRINT_ATTRIBUTE(HSA_AGENT_INFO_VERSION_MINOR, prop.version_minor, "");
|
||||
}
|
||||
|
||||
void HsaTest::PrintPeers(hsa_agent_t agent) {
|
||||
std::cout << "Peer GPUs: ";
|
||||
std::vector<hsa_agent_t> gpu_peers;
|
||||
GetGpuPeer(agent, gpu_peers);
|
||||
if (gpu_peers.size() > 0) {
|
||||
for (hsa_agent_t peer_agent : gpu_peers) {
|
||||
// Get the index of the peer in gpus_.
|
||||
size_t peer_idx = 0;
|
||||
for (; peer_idx < gpus_.size(); ++peer_idx) {
|
||||
if (peer_agent.handle == gpus_[peer_idx].handle) {
|
||||
std::cout << "GPU[" << peer_idx << "] ";
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
std::cout << std::endl;
|
||||
} else {
|
||||
std::cout << "No peer GPUs\n";
|
||||
}
|
||||
}
|
||||
|
||||
void HsaTest::PrintPoolInfo(PoolProps& prop) {
|
||||
const char* segment_strings[] = {
|
||||
"HSA_SEGMENT_GLOBAL", "HSA_AMD_SEGMENT_READONLY",
|
||||
"HSA_AMD_SEGMENT_PRIVATE", "HSA_AMD_SEGMENT_GROUP"};
|
||||
PRINT_ATTRIBUTE(HSA_AMD_MEMORY_POOL_INFO_SEGMENT,
|
||||
segment_strings[prop.segment], "");
|
||||
|
||||
std::string global_flag = "";
|
||||
global_flag +=
|
||||
(prop.global_flag & HSA_AMD_MEMORY_POOL_GLOBAL_FLAG_KERNARG_INIT)
|
||||
? "HSA_AMD_MEMORY_POOL_GLOBAL_FLAG_KERNARG_INIT | "
|
||||
: "";
|
||||
global_flag +=
|
||||
(prop.global_flag & HSA_AMD_MEMORY_POOL_GLOBAL_FLAG_FINE_GRAINED)
|
||||
? "HSA_AMD_MEMORY_POOL_GLOBAL_FLAG_FINE_GRAINED | "
|
||||
: "";
|
||||
global_flag +=
|
||||
(prop.global_flag & HSA_AMD_MEMORY_POOL_GLOBAL_FLAG_COARSE_GRAINED)
|
||||
? "HSA_AMD_MEMORY_POOL_GLOBAL_FLAG_COARSE_GRAINED "
|
||||
: "";
|
||||
PRINT_ATTRIBUTE(HSA_AMD_MEMORY_POOL_INFO_GLOBAL_FLAGS, global_flag, "");
|
||||
|
||||
static const size_t kMb = 1024 * 1024;
|
||||
if (prop.size >= kMb) {
|
||||
PRINT_ATTRIBUTE(HSA_AMD_MEMORY_POOL_INFO_SIZE, ToMB(prop.size), "MB");
|
||||
} else {
|
||||
PRINT_ATTRIBUTE(HSA_AMD_MEMORY_POOL_INFO_SIZE, prop.size, "bytes");
|
||||
}
|
||||
|
||||
PRINT_ATTRIBUTE(HSA_AMD_MEMORY_POOL_INFO_RUNTIME_ALLOC_ALLOWED,
|
||||
prop.alloc_allowed, "");
|
||||
PRINT_ATTRIBUTE(HSA_AMD_MEMORY_POOL_INFO_RUNTIME_ALLOC_GRANULE,
|
||||
prop.alloc_granule, "bytes");
|
||||
PRINT_ATTRIBUTE(HSA_AMD_MEMORY_POOL_INFO_RUNTIME_ALLOC_ALIGNMENT,
|
||||
prop.alloc_alignment, "bytes");
|
||||
PRINT_ATTRIBUTE(HSA_AMD_MEMORY_POOL_INFO_ACCESSIBLE_BY_ALL,
|
||||
prop.all_accessible, "");
|
||||
}
|
||||
@@ -0,0 +1,124 @@
|
||||
#ifndef HSA_TEST_H
|
||||
#define HSA_TEST_H
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "hsa.h"
|
||||
#include "hsa_ext_amd.h"
|
||||
#include "hsa_ext_finalize.h"
|
||||
|
||||
#include "HSAILTool.h"
|
||||
|
||||
class HsaTest {
|
||||
public:
|
||||
HsaTest(const char* test_name);
|
||||
virtual ~HsaTest();
|
||||
|
||||
void Init();
|
||||
void Cleanup();
|
||||
|
||||
virtual void Run() = 0;
|
||||
|
||||
protected:
|
||||
static hsa_status_t IterateAgents(hsa_agent_t agent, void* data);
|
||||
static hsa_status_t IteratePools(hsa_amd_memory_pool_t pool, void* data);
|
||||
|
||||
typedef struct AgentProps {
|
||||
AgentProps(hsa_agent_t);
|
||||
|
||||
char name[64];
|
||||
char vendor_name[64];
|
||||
hsa_agent_feature_t feature;
|
||||
hsa_machine_model_t machine_model;
|
||||
hsa_profile_t profile;
|
||||
hsa_default_float_rounding_mode_t default_float_rounding_mode;
|
||||
hsa_default_float_rounding_mode_t base_profile_float_rounding_mode;
|
||||
bool fast_f16_operation;
|
||||
uint32_t wavefront_size;
|
||||
uint16_t workgroup_max_dim[3];
|
||||
uint32_t workgroup_max_size;
|
||||
hsa_dim3_t grid_max_dim;
|
||||
uint32_t grid_max_size;
|
||||
uint32_t fbarrier_max_size;
|
||||
uint32_t queue_max;
|
||||
uint32_t queue_min_size;
|
||||
uint32_t queue_max_size;
|
||||
hsa_queue_type_t queue_type;
|
||||
uint32_t node;
|
||||
hsa_device_type_t device_type;
|
||||
uint32_t cache_size[4];
|
||||
hsa_isa_t isa;
|
||||
uint8_t extensions[128];
|
||||
uint16_t version_major;
|
||||
uint16_t version_minor;
|
||||
} AgentProps;
|
||||
|
||||
typedef struct PoolProps {
|
||||
PoolProps(hsa_amd_memory_pool_t pool);
|
||||
|
||||
hsa_amd_segment_t segment;
|
||||
hsa_amd_memory_pool_global_flag_t global_flag;
|
||||
size_t size;
|
||||
bool alloc_allowed;
|
||||
size_t alloc_granule;
|
||||
size_t alloc_alignment;
|
||||
bool all_accessible;
|
||||
} PoolProps;
|
||||
|
||||
class Kernel {
|
||||
public:
|
||||
Kernel(hsa_agent_t agent, std::string hsail_file);
|
||||
|
||||
virtual ~Kernel();
|
||||
|
||||
uint64_t GetCodeHandle(const char* kernel_name);
|
||||
hsa_status_t GetScratchSize(uint32_t* size);
|
||||
|
||||
protected:
|
||||
virtual void Initialize();
|
||||
|
||||
virtual void Cleanup();
|
||||
|
||||
bool CreateProgramFromHsailFile();
|
||||
|
||||
bool CreateCodeObjectAndExecutable();
|
||||
|
||||
HSAIL_ASM::Tool tool_;
|
||||
|
||||
hsa_agent_t agent_;
|
||||
hsa_profile_t profile_;
|
||||
|
||||
hsa_ext_program_t program_;
|
||||
hsa_code_object_t code_object_;
|
||||
hsa_executable_t executable_;
|
||||
hsa_executable_symbol_t kernel_symbol_;
|
||||
|
||||
std::string hsail_file_;
|
||||
};
|
||||
|
||||
virtual void GetGpuPeer(hsa_agent_t master,
|
||||
std::vector<hsa_agent_t>& gpu_peers);
|
||||
virtual void* AllocateSystemMemory(bool fine_grain, size_t size);
|
||||
virtual void* AllocateLocalMemory(hsa_agent_t agent, size_t size);
|
||||
virtual void FreeMemory(void* ptr);
|
||||
|
||||
virtual void LaunchPacket(hsa_queue_t& queue, hsa_packet_type_t type,
|
||||
void* packet);
|
||||
|
||||
virtual void PrintAgentInfo(AgentProps& prop);
|
||||
virtual void PrintPeers(hsa_agent_t agent);
|
||||
virtual void PrintPoolInfo(PoolProps& prop);
|
||||
|
||||
std::string test_name_;
|
||||
|
||||
std::vector<hsa_agent_t> cpus_;
|
||||
std::vector<hsa_agent_t> gpus_;
|
||||
|
||||
std::map<uint64_t, hsa_amd_memory_pool_t> global_fine_;
|
||||
std::map<uint64_t, hsa_amd_memory_pool_t> global_coarse_;
|
||||
std::map<uint64_t, hsa_amd_memory_pool_t> group_;
|
||||
};
|
||||
|
||||
#endif // HSA_TEST_H
|
||||
@@ -0,0 +1,190 @@
|
||||
#include "hsatimer.h"
|
||||
|
||||
PerfTimer::PerfTimer()
|
||||
{
|
||||
freq_in_100mhz = MeasureTSCFreqHz();
|
||||
}
|
||||
|
||||
PerfTimer::~PerfTimer()
|
||||
{
|
||||
while(!_timers.empty())
|
||||
{
|
||||
Timer *temp = _timers.back();
|
||||
_timers.pop_back();
|
||||
delete temp;
|
||||
}
|
||||
}
|
||||
|
||||
//a new cretaed timer instantance index will be returned
|
||||
int PerfTimer::CreateTimer()
|
||||
{
|
||||
Timer *newTimer = new Timer;
|
||||
newTimer->_start = 0;
|
||||
newTimer->_clocks = 0;
|
||||
|
||||
#ifdef _WIN32
|
||||
QueryPerformanceFrequency((LARGE_INTEGER*)&newTimer->_freq);
|
||||
#else
|
||||
newTimer->_freq = (long long)1.0E3;
|
||||
#endif
|
||||
|
||||
/* Push back the address of new Timer instance created */
|
||||
_timers.push_back(newTimer);
|
||||
return (int)(_timers.size() - 1);
|
||||
}
|
||||
|
||||
int PerfTimer::StartTimer(int index)
|
||||
{
|
||||
if(index >= (int)_timers.size())
|
||||
{
|
||||
Error("Cannot reset timer. Invalid handle.");
|
||||
return HSA_FAILURE;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
// General Windows timing method
|
||||
#ifndef _AMD
|
||||
long long tmpStart;
|
||||
QueryPerformanceCounter((LARGE_INTEGER*)&(tmpStart));
|
||||
_timers[index]->_start = (double)tmpStart;
|
||||
#else
|
||||
// AMD Windows timing method
|
||||
|
||||
#endif
|
||||
|
||||
#else
|
||||
// General Linux timing method
|
||||
#ifndef _AMD
|
||||
struct timeval s;
|
||||
gettimeofday(&s, 0);
|
||||
_timers[index]->_start = s.tv_sec * 1.0E3 + ((double)(s.tv_usec / 1.0E3));
|
||||
#else
|
||||
|
||||
// AMD timing method
|
||||
|
||||
unsigned int unused;
|
||||
_timers[index]->_start = __rdtscp(&unused);
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
return HSA_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
int PerfTimer::StopTimer(int index)
|
||||
{
|
||||
double n=0;
|
||||
if(index >= (int)_timers.size())
|
||||
{
|
||||
Error("Cannot reset timer. Invalid handle.");
|
||||
return HSA_FAILURE;
|
||||
}
|
||||
#ifdef _WIN32
|
||||
#ifndef _AMD
|
||||
long long n1;
|
||||
QueryPerformanceCounter((LARGE_INTEGER*)&(n1));
|
||||
n = (double) n1;
|
||||
#else
|
||||
|
||||
// AMD Window Timing
|
||||
|
||||
#endif
|
||||
|
||||
#else
|
||||
// General Linux timing method
|
||||
#ifndef _AMD
|
||||
struct timeval s;
|
||||
gettimeofday(&s, 0);
|
||||
n = s.tv_sec * 1.0E3+ (double)(s.tv_usec/1.0E3);
|
||||
#else
|
||||
// AMD Linux timing
|
||||
|
||||
unsigned int unused;
|
||||
n = __rdtscp(&unused);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
n -= _timers[index]->_start;
|
||||
_timers[index]->_start = 0;
|
||||
|
||||
#ifndef _AMD
|
||||
_timers[index]->_clocks += n;
|
||||
#else
|
||||
//_timers[index]->_clocks += 10 * n /freq_in_100mhz; // unit is ns
|
||||
_timers[index]->_clocks += 1.0E-6 * 10 * n /freq_in_100mhz; // convert to ms
|
||||
cout << "_AMD is enabled!!!" << endl;
|
||||
#endif
|
||||
|
||||
return HSA_SUCCESS;
|
||||
}
|
||||
|
||||
void PerfTimer::Error(string str)
|
||||
{
|
||||
cout << str << endl;
|
||||
}
|
||||
|
||||
|
||||
double PerfTimer::ReadTimer(int index)
|
||||
{
|
||||
|
||||
if(index >= (int)_timers.size())
|
||||
{
|
||||
Error("Cannot read timer. Invalid handle.");
|
||||
return HSA_FAILURE;
|
||||
}
|
||||
|
||||
double reading = double(_timers[index]->_clocks);
|
||||
|
||||
reading = double(reading / _timers[index]->_freq);
|
||||
|
||||
return reading;
|
||||
}
|
||||
|
||||
|
||||
uint64_t PerfTimer::CoarseTimestampUs()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
uint64_t freqHz, ticks;
|
||||
QueryPerformanceFrequency((LARGE_INTEGER *)&freqHz);
|
||||
QueryPerformanceCounter((LARGE_INTEGER *)&ticks);
|
||||
|
||||
// Scale numerator and divisor until (ticks * 1000000) fits in uint64_t.
|
||||
while (ticks > (1ULL << 44)) {
|
||||
ticks /= 16;
|
||||
freqHz /= 16;
|
||||
}
|
||||
|
||||
return (ticks * 1000000) / freqHz;
|
||||
#else
|
||||
struct timespec ts;
|
||||
clock_gettime(CLOCK_MONOTONIC_RAW, &ts);
|
||||
return uint64_t(ts.tv_sec) * 1000000 + ts.tv_nsec / 1000;
|
||||
#endif
|
||||
}
|
||||
|
||||
uint64_t PerfTimer::MeasureTSCFreqHz()
|
||||
{
|
||||
// Make a coarse interval measurement of TSC ticks for 1 gigacycles.
|
||||
unsigned int unused;
|
||||
uint64_t tscTicksEnd;
|
||||
|
||||
uint64_t coarseBeginUs = CoarseTimestampUs();
|
||||
uint64_t tscTicksBegin = __rdtscp(&unused);
|
||||
do
|
||||
{
|
||||
tscTicksEnd = __rdtscp(&unused);
|
||||
}
|
||||
while (tscTicksEnd - tscTicksBegin < 1000000000);
|
||||
|
||||
uint64_t coarseEndUs = CoarseTimestampUs();
|
||||
|
||||
// Compute the TSC frequency and round to nearest 100MHz.
|
||||
uint64_t coarseIntervalNs = (coarseEndUs - coarseBeginUs) * 1000;
|
||||
uint64_t tscIntervalTicks = tscTicksEnd - tscTicksBegin;
|
||||
return (tscIntervalTicks * 10 + (coarseIntervalNs / 2)) / coarseIntervalNs;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
#ifndef __MYTIME__
|
||||
#define __MYTIME__
|
||||
|
||||
// Will use AMD timer and general Linux timer based on users' need --> compilation flag
|
||||
// need to consider platform is Windows or Linux
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
using namespace std;
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#include <time.h>
|
||||
#include <windows.h>
|
||||
#include <intrin.h>
|
||||
#else
|
||||
#if defined(__GNUC__)
|
||||
#include <sys/time.h>
|
||||
#include <x86intrin.h>
|
||||
#endif // __GNUC__
|
||||
#endif //_MSC_VER
|
||||
|
||||
#define HSA_FAILURE 1
|
||||
#define HSA_SUCCESS 0
|
||||
|
||||
class PerfTimer {
|
||||
private:
|
||||
struct Timer
|
||||
{
|
||||
string name; /* < name name of time object*/
|
||||
long long _freq; /* < _freq frequency*/
|
||||
double _clocks; /* < _clocks number of ticks at end*/
|
||||
double _start; /* < _start start point ticks*/
|
||||
};
|
||||
|
||||
std::vector<Timer*> _timers; /*< _timers vector to Timer objects */
|
||||
double freq_in_100mhz;
|
||||
|
||||
public:
|
||||
PerfTimer();
|
||||
~PerfTimer();
|
||||
|
||||
private:
|
||||
//AMD timing method
|
||||
uint64_t CoarseTimestampUs();
|
||||
uint64_t MeasureTSCFreqHz();
|
||||
|
||||
//General Linux timing method
|
||||
|
||||
public:
|
||||
int CreateTimer();
|
||||
int StartTimer(int index);
|
||||
int StopTimer(int index);
|
||||
|
||||
public:
|
||||
// retrieve time
|
||||
double ReadTimer(int index);
|
||||
// write into a file
|
||||
double WriteTimer(int index);
|
||||
|
||||
public:
|
||||
void Error(string str);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
Executable
+45
@@ -0,0 +1,45 @@
|
||||
#ifdef _WIN32 // Compiling for Windows Platform
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <Windows.h>
|
||||
#include "os.h"
|
||||
#include <stdio.h>
|
||||
|
||||
void SetEnv(const char* env_var_name, const char* env_var_value) {
|
||||
BOOL err = SetEnvironmentVariable(env_var_name, env_var_value);
|
||||
if(FALSE == err){
|
||||
printf("Set environment variable failed!\n");
|
||||
exit(1);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
char* GetEnv(const char* env_var_name){
|
||||
char* buff;
|
||||
DWORD char_count = GetEnvironmentVariable(env_var_name, NULL, 0);
|
||||
if (char_count == 0) return NULL;
|
||||
buff = (char*)malloc(sizeof(char) * char_count);
|
||||
GetEnvironmentVariable(env_var_name, buff, char_count);
|
||||
buff[char_count - 1] = '\0';
|
||||
return buff;
|
||||
}
|
||||
|
||||
#elif defined(__linux__)
|
||||
|
||||
#include "os.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
void SetEnv(const char* env_var_name, const char* env_var_value){
|
||||
int err = setenv(env_var_name, env_var_value, 1);
|
||||
if(0 != err){
|
||||
printf("Set environment variable failed!\n");
|
||||
exit(1);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
char* GetEnv(const char* env_var_name) {
|
||||
return getenv(env_var_name);
|
||||
}
|
||||
|
||||
#endif
|
||||
Executable
+12
@@ -0,0 +1,12 @@
|
||||
#ifndef HSA_PERF_SRC_UTILS_OS_H_
|
||||
#define HSA_PERF_SRC_UTILS_OS_H_
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
// Set envriroment variable
|
||||
void SetEnv(const char* env_var_name, const char* env_var_value);
|
||||
|
||||
// Get the value of enviroment
|
||||
char* GetEnv(const char* env_var_name);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,193 @@
|
||||
#include "utilities.h"
|
||||
|
||||
/*
|
||||
* Prints no more than 256 elements of the given array.
|
||||
* Prints full array if length is less than 256.
|
||||
* Prints Array name followed by elements.
|
||||
*/
|
||||
template<typename T>
|
||||
void PrintArray(
|
||||
string header,
|
||||
const T * data,
|
||||
const int width,
|
||||
const int height)
|
||||
{
|
||||
cout<<"\n"<<header<<"\n";
|
||||
for(int i = 0; i < height; i++)
|
||||
{
|
||||
for(int j = 0; j < width; j++)
|
||||
{
|
||||
cout<<data[i*width+j]<<" ";
|
||||
}
|
||||
cout<<"\n";
|
||||
}
|
||||
cout<<"\n";
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
int IsPowerOf2(T val)
|
||||
{
|
||||
long long _val = val;
|
||||
if((_val & (-_val))-_val == 0 && _val != 0)
|
||||
return 0;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
template<typename T>
|
||||
T RoundToPowerOf2(T val)
|
||||
{
|
||||
int bytes = sizeof(T);
|
||||
|
||||
val--;
|
||||
for(int i = 0; i < bytes; i++)
|
||||
val |= val >> (1<<i);
|
||||
val++;
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
int FillRandom(
|
||||
T * arrayPtr,
|
||||
const int width,
|
||||
const int height,
|
||||
const T rangeMin,
|
||||
const T rangeMax,
|
||||
unsigned int seed)
|
||||
{
|
||||
if(!arrayPtr)
|
||||
{
|
||||
printf("Cannot fill array. NULL pointer.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(!seed)
|
||||
seed = (unsigned int)time(NULL);
|
||||
|
||||
srand(seed);
|
||||
double range = double(rangeMax - rangeMin) + 1.0;
|
||||
|
||||
/* random initialisation of input */
|
||||
for(int i = 0; i < height; i++)
|
||||
for(int j = 0; j < width; j++)
|
||||
{
|
||||
int index = i*width + j;
|
||||
arrayPtr[index] = rangeMin + T(range*rand()/(RAND_MAX + 1.0));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if 0
|
||||
//get a memory region that can be used for global memory allocations.
|
||||
hsa_status_t get_global_region(hsa_region_t region, void* data)
|
||||
{
|
||||
hsa_region_segment_t segment;
|
||||
hsa_region_get_info(region, HSA_REGION_INFO_SEGMENT, &segment);
|
||||
if (HSA_REGION_SEGMENT_GLOBAL == segment)
|
||||
{
|
||||
hsa_region_t* ret = (hsa_region_t*) data;
|
||||
*ret = region;
|
||||
}
|
||||
return HSA_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Finds the specified symbols offset in the specified brig_module.
|
||||
* If the symbol is found the function returns HSA_STATUS_SUCCESS,
|
||||
* otherwise it returns HSA_STATUS_ERROR.
|
||||
*/
|
||||
hsa_status_t find_symbol_offset(hsa_ext_brig_module_t* brig_module,
|
||||
char* symbol_name,
|
||||
hsa_ext_brig_code_section_offset32_t* offset)
|
||||
{
|
||||
|
||||
/*
|
||||
* Get the data section
|
||||
*/
|
||||
hsa_ext_brig_section_header_t* data_section_header =
|
||||
brig_module->section[HSA_EXT_BRIG_SECTION_DATA];
|
||||
/*
|
||||
* Get the code section
|
||||
*/
|
||||
hsa_ext_brig_section_header_t* code_section_header =
|
||||
brig_module->section[HSA_EXT_BRIG_SECTION_CODE];
|
||||
|
||||
/*
|
||||
* First entry into the BRIG code section
|
||||
*/
|
||||
BrigCodeOffset32_t code_offset = code_section_header->header_byte_count;
|
||||
BrigBase* code_entry = (BrigBase*) ((char*)code_section_header + code_offset);
|
||||
while (code_offset != code_section_header->byte_count)
|
||||
{
|
||||
if (code_entry->kind == BRIG_KIND_DIRECTIVE_KERNEL)
|
||||
{
|
||||
/*
|
||||
* Now find the data in the data section
|
||||
*/
|
||||
BrigDirectiveExecutable* directive_kernel = (BrigDirectiveExecutable*) (code_entry);
|
||||
BrigDataOffsetString32_t data_name_offset = directive_kernel->name;
|
||||
BrigData* data_entry = (BrigData*)((char*) data_section_header + data_name_offset);
|
||||
if (!strncmp(symbol_name, (char*) data_entry->bytes, strlen(symbol_name)))
|
||||
{
|
||||
*offset = code_offset;
|
||||
return HSA_STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
code_offset += code_entry->byteCount;
|
||||
code_entry = (BrigBase*) ((char*)code_section_header + code_offset);
|
||||
}
|
||||
return HSA_STATUS_ERROR;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Determines if the given agent is of type HSA_DEVICE_TYPE_GPU
|
||||
* and sets the value of data to the agent handle if it is.
|
||||
*/
|
||||
hsa_status_t find_gpu(hsa_agent_t agent, void *data)
|
||||
{
|
||||
if (data == NULL)
|
||||
{
|
||||
return HSA_STATUS_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
hsa_device_type_t device_type;
|
||||
hsa_status_t stat = hsa_agent_get_info(agent, HSA_AGENT_INFO_DEVICE, &device_type);
|
||||
if (stat != HSA_STATUS_SUCCESS)
|
||||
{
|
||||
return stat;
|
||||
}
|
||||
if (device_type == HSA_DEVICE_TYPE_GPU)
|
||||
{
|
||||
*((hsa_agent_t *)data) = agent;
|
||||
}
|
||||
return HSA_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Determines if a memory region can be used for kernarg
|
||||
* allocations.
|
||||
*/
|
||||
hsa_status_t get_memory_region(hsa_region_t region, void* data)
|
||||
{
|
||||
hsa_region_global_flag_t flags;
|
||||
hsa_region_get_info(region, HSA_REGION_INFO_GLOBAL_FLAGS, &flags);
|
||||
|
||||
MemRegion *my_mem_region = (MemRegion *)data;
|
||||
|
||||
if (flags & HSA_REGION_GLOBAL_FLAG_COARSE_GRAINED) {
|
||||
my_mem_region->coarse_region = region;
|
||||
}
|
||||
|
||||
if (flags & HSA_REGION_GLOBAL_FLAG_KERNARG)
|
||||
{
|
||||
my_mem_region->kernarg_region= region;
|
||||
}
|
||||
|
||||
return HSA_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,236 @@
|
||||
#ifndef __HSA_UTILITY__
|
||||
#define __HSA_UTILITY__
|
||||
|
||||
#include <vector>
|
||||
#include <thread>
|
||||
|
||||
#include "hsa.h"
|
||||
#include "hsa_ext_finalize.h"
|
||||
|
||||
#include <string.h>
|
||||
#include<iostream>
|
||||
using namespace std;
|
||||
|
||||
|
||||
|
||||
#define HSA_ARGUMENT_ALIGN_BYTES 16
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#define ALIGNED_(x) __declspec(align(x))
|
||||
|
||||
#pragma warning(disable: 4800)
|
||||
#pragma warning(disable: 4305) // truncation from 'double' to 'const float'
|
||||
#pragma warning(disable: 4267) // conversion from 'size_t' to 'int', possible loss of data
|
||||
|
||||
typedef unsigned int uint;
|
||||
|
||||
#else
|
||||
#if defined(__GNUC__)
|
||||
#define ALIGNED_(x) __attribute__ ((aligned(x)))
|
||||
#endif // __GNUC__
|
||||
#endif // _MSC_VER
|
||||
|
||||
#define SDK_FAILURE 1
|
||||
#define SDK_SUCCESS 0
|
||||
|
||||
/*
|
||||
#define check(msg, status) \
|
||||
if (status != HSA_STATUS_SUCCESS) { \
|
||||
printf("%s failed.\n", #msg); \
|
||||
exit(1); \
|
||||
} else { \
|
||||
printf("%s succeeded.\n", #msg); \
|
||||
}
|
||||
*/
|
||||
#define check(msg, status) \
|
||||
if (status != HSA_STATUS_SUCCESS) { \
|
||||
printf("%s failed.\n", #msg); \
|
||||
exit(1); \
|
||||
} else { \
|
||||
; \
|
||||
}
|
||||
|
||||
/*
|
||||
* Define required BRIG data structures.
|
||||
*/
|
||||
|
||||
typedef uint32_t BrigCodeOffset32_t;
|
||||
|
||||
typedef uint32_t BrigDataOffset32_t;
|
||||
|
||||
typedef uint16_t BrigKinds16_t;
|
||||
|
||||
typedef uint8_t BrigLinkage8_t;
|
||||
|
||||
typedef uint8_t BrigExecutableModifier8_t;
|
||||
|
||||
typedef BrigDataOffset32_t BrigDataOffsetString32_t;
|
||||
|
||||
typedef struct {
|
||||
// memory region accessed by GPU only
|
||||
hsa_region_t coarse_region;
|
||||
|
||||
// system memory access by gpu and cpu
|
||||
hsa_region_t kernarg_region;
|
||||
|
||||
} MemRegion;
|
||||
|
||||
|
||||
/*
|
||||
enum BrigKinds {
|
||||
BRIG_KIND_NONE = 0x0000,
|
||||
BRIG_KIND_DIRECTIVE_BEGIN = 0x1000,
|
||||
BRIG_KIND_DIRECTIVE_KERNEL = 0x1008,
|
||||
};
|
||||
|
||||
typedef struct BrigBase BrigBase;
|
||||
struct BrigBase {
|
||||
uint16_t byteCount;
|
||||
BrigKinds16_t kind;
|
||||
};
|
||||
|
||||
typedef struct BrigExecutableModifier BrigExecutableModifier;
|
||||
struct BrigExecutableModifier {
|
||||
BrigExecutableModifier8_t allBits;
|
||||
};
|
||||
|
||||
typedef struct BrigDirectiveExecutable BrigDirectiveExecutable;
|
||||
struct BrigDirectiveExecutable {
|
||||
uint16_t byteCount;
|
||||
BrigKinds16_t kind;
|
||||
BrigDataOffsetString32_t name;
|
||||
uint16_t outArgCount;
|
||||
uint16_t inArgCount;
|
||||
BrigCodeOffset32_t firstInArg;
|
||||
BrigCodeOffset32_t firstCodeBlockEntry;
|
||||
BrigCodeOffset32_t nextModuleEntry;
|
||||
uint32_t codeBlockEntryCount;
|
||||
BrigExecutableModifier modifier;
|
||||
BrigLinkage8_t linkage;
|
||||
uint16_t reserved;
|
||||
};
|
||||
|
||||
typedef struct BrigData BrigData;
|
||||
struct BrigData {
|
||||
uint32_t byteCount;
|
||||
uint8_t bytes[1];
|
||||
};
|
||||
*/
|
||||
|
||||
struct float2
|
||||
{
|
||||
float s0;
|
||||
float s1;
|
||||
|
||||
|
||||
float2 operator * (float2 &fl)
|
||||
{
|
||||
float2 temp;
|
||||
temp.s0 = (this->s0) * fl.s0;
|
||||
temp.s1 = (this->s1) * fl.s1;
|
||||
return temp;
|
||||
}
|
||||
|
||||
float2 operator * (float scalar)
|
||||
{
|
||||
float2 temp;
|
||||
temp.s0 = (this->s0) * scalar;
|
||||
temp.s1 = (this->s1) * scalar;
|
||||
return temp;
|
||||
}
|
||||
|
||||
float2 operator + (float2 &fl)
|
||||
{
|
||||
float2 temp;
|
||||
temp.s0 = (this->s0) + fl.s0;
|
||||
temp.s1 = (this->s1) + fl.s1;
|
||||
return temp;
|
||||
}
|
||||
|
||||
float2 operator - (float2 fl)
|
||||
{
|
||||
float2 temp;
|
||||
temp.s0 = (this->s0) - fl.s0;
|
||||
temp.s1 = (this->s1) - fl.s1;
|
||||
return temp;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct uint2
|
||||
{
|
||||
uint s0;
|
||||
uint s1;
|
||||
|
||||
|
||||
uint2 operator * (uint2 &fl)
|
||||
{
|
||||
uint2 temp;
|
||||
temp.s0 = (this->s0) * fl.s0;
|
||||
temp.s1 = (this->s1) * fl.s1;
|
||||
return temp;
|
||||
}
|
||||
|
||||
uint2 operator * (float scalar)
|
||||
{
|
||||
uint2 temp;
|
||||
temp.s0 = (this->s0) * scalar;
|
||||
temp.s1 = (this->s1) * scalar;
|
||||
return temp;
|
||||
}
|
||||
|
||||
uint2 operator + (uint2 &fl)
|
||||
{
|
||||
uint2 temp;
|
||||
temp.s0 = (this->s0) + fl.s0;
|
||||
temp.s1 = (this->s1) + fl.s1;
|
||||
return temp;
|
||||
}
|
||||
|
||||
uint2 operator - (uint2 fl)
|
||||
{
|
||||
uint2 temp;
|
||||
temp.s0 = (this->s0) - fl.s0;
|
||||
temp.s1 = (this->s1) - fl.s1;
|
||||
return temp;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Prints no more than 256 elements of the given array.
|
||||
* Prints full array if length is less than 256.
|
||||
* Prints Array name followed by elements.
|
||||
*/
|
||||
template<typename T> void PrintArray(string header, const T * data, const int width, const int height);
|
||||
|
||||
template<typename T> int IsPowerOf2(T val);
|
||||
|
||||
template<typename T> T RoundToPowerOf2(T val);
|
||||
|
||||
template<typename T> int FillRandom(T * arrayPtr, const int width, const int height, const T rangeMin, const T rangeMax, unsigned int seed=123);
|
||||
|
||||
//get a memory region that can be used for global memory allocations.
|
||||
hsa_status_t get_global_region(hsa_region_t region, void* data);
|
||||
|
||||
/*
|
||||
* Finds the specified symbols offset in the specified brig_module.
|
||||
* If the symbol is found the function returns HSA_STATUS_SUCCESS,
|
||||
* otherwise it returns HSA_STATUS_ERROR.
|
||||
*/
|
||||
|
||||
//hsa_status_t find_symbol_offset(hsa_ext_brig_module_t* brig_module, char* symbol_name, hsa_ext_brig_code_section_offset32_t* offset);
|
||||
|
||||
/*
|
||||
* Determines if the given agent is of type HSA_DEVICE_TYPE_GPU
|
||||
* and sets the value of data to the agent handle if it is.
|
||||
*/
|
||||
hsa_status_t find_gpu(hsa_agent_t agent, void *data);
|
||||
|
||||
/*
|
||||
* Determines if a memory region can be used for kernarg
|
||||
* allocations.
|
||||
*/
|
||||
hsa_status_t get_memory_region(hsa_region_t region, void* data);
|
||||
|
||||
#endif
|
||||
Fai riferimento in un nuovo problema
Block a user