翻译HoudiniEngine官方文档:Sessions

2024-09-06 23:18

本文主要是介绍翻译HoudiniEngine官方文档:Sessions,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

官方文档:《Houdini Engine 3.6: Sessions》

介绍

session的概念是在 Houdini Engine 2.x 中引入的。 在先前版本中,Houdini Engine 的动态链接库,也就是libHAPI,会直接链接到Houdini的核心组件,而宿主程序通常又链接到libHAPI。 这意味着 Houdini Engine 的实现是在宿主进程中运行的。

这一设计有两个主要问题:

  • 因为libHAPI在宿主进程中加载了核心的Houdini库,而这些库又有多个第三方依赖项。因此它们很可能与宿主应用程序自身的依赖项发生冲突
  • 每一个进程只能有一个Houdini场景。

在 Houdini Engine 3.x 中,我们仍支持这种“进程内”的形式——这对于简单的宿主程序可能仍旧是一个不错的选择。然而,我们还提供了一种新的 IPC(inter-process communication:进程间通信) 机制。这样,宿主应用程序可以运行多个session——在它自己的进程中或单独的进程中——以并行的方式或是在其他机器上(如果需要的话)。

每一个这样的session都用 HAPI_Session 来表示,大多数HAPI中的函数都需要它作为参数。

进程外(Out-of-process)

另一方面,如果你想利用 “IPC实现” 的优势,或者说你想以较低的开销轻松地在 “IPC实现” 与 “进程内实现” 做切换,你应该将你的应用链接到libHAPILlibHAPIL代表 Houdini Engine API Loader,它是一个充当 “楔子”(shim) 的库,它可以加载libHAPIlibHARC(我们的IPC客户端实现)、或者甚至是一个用户提供的动态库。

libHAPIL导出在HAPI.h中声明的函数。这些函数中的大多数都被重定向到一个动态链接实现的库(例如libHAPIlibHARC),而其他函数是用于加载库和创建session的特殊函数,并在libHAPIL本身中实现。

如果你将应用链接到libHAPIL,那么你必须在调用任何使用session作为参数的HAPI函数(包括HAPI_Initialize())之前,显式地创建一个session

比如说,HAPI_CreateInProcessSession() 动态加载libHAPI并在其输出参数中返回一个 “进程内session” 的单例。 请注意,在调用此函数之前,不会有任何Houdini库和依赖项在宿主进程中加载。 这可能有助于解决依赖关系问题。

你可以在调用HAPI_CreateInProcessSession()时传入 NULL 表示被创建的 “进程内session” 的单例。

如果你想使用我们的 “基于Thrift的IPC实现”,那么在创建session时,你可以:

  • 使用HAPI_CreateThriftSocketSession()(使用“TCP sockets”作为传输层)
  • 或者HAPI_CreateThriftNamedPipeSession()(在Windows系统上使用“named pipes”,在类Unix系统上使用“domain sockets”)

首次创建Thrift的session时,libHAPIL会加载libHARC,即客户端的动态库,为HAPI调用实现Thrift绑定。

你甚至可以实现自己定义的IPC客户端库,使用HAPI_BindCustomImplementation()将其绑定到HAPI_SessionType枚举中的自定义插槽之一,并使用HAPI_CreateCustomSession()创建基于此实现的session,并将创建session所需的参数作为原始指针传递。

最后,当session的工作结束了之后,可以使用HAPI_CloseSession()将其关闭。 在libHARC实现中,这将关闭客户端与服务器的连接。 如果在客户端的生存期内未使用HAPI_CloseSession()显式地关闭session,则在客户端进程终止时将自动关闭该session

使用“自动关闭”这个选项创建session时,关联的服务器进程将在最后一个session关闭时终止。 请注意,在非Windows系统上,必须在宿主应用程序中处理“SIGCHLD event”,以使服务器进程完全终止并返回 license。

请注意,session可以打开多个,实现的库也可以同时加载多个。

这是个简单的示例,展示了如何启动和连接一个 “进程外session”,以及如何初始化Houdini Engine API。

// HARS(Houdini-Engine API Remote Server)选项
HAPI_ThriftServerOptions serverOptions{ 0 };
serverOptions.autoClose = true;
serverOptions.timeoutMs = 3000.0f;
// 使用"hapi"名字的 Named Pipe 来创建我们的HARS服务器
// 如果你之前已经手动启动了 HARS,则可以忽略这个调用
if (HAPI_RESULT_SUCCESS != HAPI_StartThriftNamedPipeServer(&serverOptions, "hapi", nullptr))return false;
// 创建一个新的 HAPI session,它会使用刚才那个服务器
HAPI_Session session;
if (HAPI_RESULT_SUCCESS != HAPI_CreateThriftNamedPipeSession(&session, "hapi"))return false;
// 初始化 HAPI
HAPI_CookOptions cookOptions = HAPI_CookOptions_Create();
if (HAPI_RESULT_SUCCESS != HAPI_Initialize(&session,           // session:你正在与之交互的 session。如果是 NULL则表示使用默认的 “进程内session”&cookOptions,       // cook options:一个全局的 cook option,后续的cook默认都会用它。//			     每次cook都可以覆盖此设置,但是如果你选择在cook_on_load设置为true的情况下实例化 asset,则将使用这个选项。true,               // use_cooking_thread:是否使用一个不同的线程来cook,这允许异步cook和更大的栈尺寸。-1,                 // cooking_thread_stack_size:设置cook线程的栈的尺寸,单位为 byte。“-1”代表使用 Houdini的默认值。"",                 // houdini_environment_files:一串路径列表(在Windows上以“;”作为分隔符,在Linux和Mac上以“:”作为分隔符)。//							  这些文件后缀为 .env 的文件遵循Houdini用户偏好文件夹中的 houdini.env 文件的格式。//							  它们将会在默认的 houdini.env 文件之后应用,并会覆盖掉进程的环境变量的值//							  你可以使用它来在运行HoudiniEngine时强制为一个更严格的环境。详见:http://www.sidefx.com/docs/houdini/basics/config_envnullptr,            // otl_search_path:OTL 的搜索路径。nullptr,            // dso_search_path:通用的 DSO(自定义插件)的搜索路径。nullptr,            // image_dso_search_path:图像的 DSO(自定义插件)的搜索路径。nullptr     ))      // audio_dso_search_path:音频的 DSO(自定义插件)的搜索路径。
{return false
}

进程内(In-Process)

如果你对使用IPC不感兴趣,只想在进程内运行 Houdini Engine,则可以将宿主应用程序直接链接到libHAPI,并且在成功调用HAPI_Initialize()之前不需要调用任何其他函数。

libHAPI包含 Houdini Engine 功能实际的实现,以及与Houdini核心组件直接进行交互的接口,但不包含IPC机制的实现。

如果是从更早的 HAPI 1.x 代码库中移植,则只需向所有HAPI调用添加HAPI_Session指针参数。 使用“进程内”的方式时,这个额外的session指针参数将被忽略,因此你需要将其设置为 NULL 以获得一致性。

HARS (Houdini-Engine API Remote Server)

在客户端上使用libHARC(基于Thrift的IPC库)时,你需要启动服务器的可执行文件HARS,该文件在Houdini安装目录中。 HARS是具有简单命令行参数的控制台应用程序:

$ HARS -h
Allowed options:-h [ --help ]             显示此帮助信息-s [ --socket-port ] arg  服务器端口(如果使用TCP Socket Session)-n [ --named-pipe ] arg   pipe的名字(如果使用named pipe session)-a [ --auto-close ]       当所有客户端被关闭时,自动关闭服务器-r [ --ready-handle ] arg 服务器准备就绪时将设置的 Win32 Event 的句柄(Windows)服务器准备就绪时将发布的 POSIX named semaphore 的名称(Linux / macOS)(用于服务器自动启动)

HARS直接链接到libHAPI、核心的Houdini库、以及它们的依赖项。 因为基于 Thrift 的 IPC 是跨平台的,所以可以在不同平台上构建并运行主进程(使用libHAPILlibHARC)和服务器进程(HARS)。

你能通过“命令行”或者“管线脚本”以所需的选项来启动一个HARS进程。然后使用相应的session创建函数,在应用程序的C ++代码中建立与服务器的客户端连接。或者,你也可以在创建session之前,方便地使用函数HAPI_StartThriftSocketServer() 或HAPI_StartThriftNamedPipeServer() 从C++代码启动服务器。这些函数都会将程序阻塞,直到服务器发出准备好服务的信号为止。也就是说,一旦这些函数成功地返回了,就说明已经可以安全地创建session了。

请注意,HARS服务器当前仅支持单个客户端连接。 如果服务器已经与一个客户端连接了,那么当第二个客户端尝试连接时,第二个客户端就会阻塞,直到第一个连接关闭。

Houdini Engine Debugger

(译者注:在新版18.5中,此功能已经被 Houdini Engine SessionSync 功能替换)

多线程

使用libHARC基于 Thrift 的 RPC 实现时,一个宿主应用程序进程可以与多个HAPIsession进行交互,每个session都以其各自的Houdini状态代表其自己的HARS进程。 这为使用Houdini Engine的应用程序打开了新的多线程可能性。 当使用来自多个线程的多个session时,libHARC被设计为“线程安全”的。

对每个session的访问都受到互斥锁的保护,因此多线程可以安全地访问一个session。但事实上,仅使用一个session是无法真正实现“并行化”的。 在操作顺序有要求的情况下,客户端代码可能还需要在单个session上执行同步操作。 例如,在处理几何体时,设置几何体属性的顺序并不重要,重要的是HAPI_CommitGeo()需要在设置所有几何体属性之后调用。

另一方面,对于多个session,并行化成为可能,因为它们的Houdini上下文是完全独立的。 以下代码示例说明了如何通过独立的session进行操作,从而在异步任务之间并行地读写每个Tile的体数据。

class testharcSession
{
public:testharcSession(){mySession.type = HAPI_SESSION_MAX;mySession.id = 0;}virtual ~testharcSession(){if (mySession.type != HAPI_SESSION_MAX){HARC_TEST_SUCCESS(HAPI_IsSessionValid(&mySession));HARC_TEST_SUCCESS(HAPI_CloseSession(&mySession));HARC_TEST_ASSERT(HAPI_IsSessionValid(&mySession) == HAPI_RESULT_INVALID_SESSION);}}virtual void open() = 0;const HAPI_Session* get(){return &mySession;}
protected:HAPI_Session mySession;
};
class testharcSimpleAutoSession : public testharcSession
{
public:testharcSimpleAutoSession(const char* session_name_suffix,size_t task_id,const HAPI_ThriftServerOptions& server_options){std::ostringstream pipe_name_os;pipe_name_os << "/tmp/testharc_threading_"<< session_name_suffix << task_id << '_'
#ifdef WIN32<< GetCurrentProcessId();
#else<< getpid();
#endifmyPipeName = pipe_name_os.str();myServerOptions = server_options;myServerOptions.autoClose = true;}virtual ~testharcSimpleAutoSession(){if (mySession.type != HAPI_SESSION_MAX){HARC_TEST_SUCCESS(HAPI_IsInitialized(&mySession));HARC_TEST_SUCCESS(HAPI_Cleanup(&mySession));
#ifndef WIN32::unlink(myPipeName.c_str());
#endif}}virtual void open(){HARC_TEST_SUCCESS(HAPI_StartThriftNamedPipeServer(&myServerOptions, myPipeName.c_str(), nullptr));HARC_TEST_SUCCESS(HAPI_CreateThriftNamedPipeSession(&mySession,myPipeName.c_str()));HAPI_CookOptions cook_options = HAPI_CookOptions_Create();cook_options.splitGeosByGroup = false;HARC_TEST_SUCCESS(HAPI_Initialize(&mySession, &cook_options, true, -1,nullptr, nullptr, nullptr, nullptr, nullptr));}
private:HAPI_ThriftServerOptions    myServerOptions;std::string                 myPipeName;
};
class testharcCopyTileValues
{
public:testharcCopyTileValues(const HAPI_Session* dst_session,const HAPI_Session* src_session,HAPI_NodeId node_id,HAPI_PartId part_id,HAPI_NodeId input_node_id,const HAPI_VolumeTileInfo& tile_info,int tile_value_count): myDstSession(dst_session), mySrcSession(src_session), myNodeId(node_id), myPartId(part_id), myInputNodeId(input_node_id), myTileInfo(tile_info), myTileValueCount(tile_value_count){}void operator()(){// 分配 Tile 数据的 Bufferstd::vector<float> tile_values(static_cast<size_t>(myTileValueCount), -5.8f);// 获得颜色数据HARC_TEST_SUCCESS(HAPI_GetVolumeTileFloatData(mySrcSession,myNodeId, myPartId,-8.8f,&myTileInfo, &tile_values.front(), myTileValueCount));// 设置输入体数据上的颜色数据HARC_TEST_SUCCESS(HAPI_SetVolumeTileFloatData(myDstSession,myInputNodeId,0,&myTileInfo, &tile_values.front(), myTileValueCount));}
private:const HAPI_Session * myDstSession;const HAPI_Session * mySrcSession;HAPI_NodeId myNodeId;HAPI_PartId myPartId;HAPI_NodeId myInputNodeId;HAPI_VolumeTileInfo myTileInfo;int myTileValueCount;
};
void
testharcCopyVolume(std::shared_ptr<testharcSession> src_session,std::shared_ptr<testharcSession> dst_session
)
{src_session->open();// 从文件加载资产库HAPI_AssetLibraryId library_id = -1;HARC_TEST_SUCCESS(HAPI_LoadAssetLibraryFromFile(src_session->get(), "HAPI_Test_Volumes_HoudiniFogColor.otl",false, &library_id));HARC_TEST_ASSERT(library_id >= 0);// 实例化资产HAPI_NodeId node_id = -1;HARC_TEST_SUCCESS(HAPI_CreateNode(src_session->get(), -1, "Object/HAPI_Test_Volumes_HoudiniFogColor",nullptr, true, &node_id));HAPI_GeoInfo geo_info;HARC_TEST_SUCCESS(HAPI_GetDisplayGeoInfo(src_session->get(), node_id, &geo_info));// 获得 part 信息,第二个(也就是说索引号是1)part应该是红色体数据const HAPI_PartId part_id = 1;// 获得 part 信息HAPI_PartInfo part_info;HARC_TEST_SUCCESS(HAPI_GetPartInfo(src_session->get(), geo_info.nodeId, part_id, &part_info));// 获得 volume 信息HAPI_VolumeInfo volume_info;HARC_TEST_SUCCESS(HAPI_GetVolumeInfo(src_session->get(), geo_info.nodeId, part_id, &volume_info));HARC_TEST_ASSERT(volume_info.tupleSize == 1);HARC_TEST_ASSERT(!volume_info.hasTaper);dst_session->open();// 创建输入节点来接收体数据HAPI_NodeId input_node_id = -1;HARC_TEST_SUCCESS(HAPI_CreateInputNode(dst_session->get(), &input_node_id, "Input_Volume"));// 设置 part 信息HARC_TEST_SUCCESS(HAPI_SetPartInfo(dst_session->get(), input_node_id, 0, &part_info));// 设置 volume 信息HARC_TEST_SUCCESS(HAPI_SetVolumeInfo(dst_session->get(), input_node_id, 0, &volume_info));// 获得第一个体数据 TileHAPI_VolumeTileInfo tile_info;HARC_TEST_SUCCESS(HAPI_GetFirstVolumeTile(src_session->get(), geo_info.nodeId, part_id, &tile_info));HARC_TEST_ASSERT(tile_info.isValid);std::vector< std::future< void > > futures;const int tile_value_count =volume_info.tileSize *volume_info.tileSize *volume_info.tileSize *volume_info.tupleSize;while (tile_info.isValid){futures.push_back(std::async(std::launch::async,testharcCopyTileValues(dst_session->get(), src_session->get(),geo_info.nodeId, part_id, input_node_id,tile_info, tile_value_count)));// 获得下一个TileHARC_TEST_SUCCESS(HAPI_GetNextVolumeTile(src_session->get(),geo_info.nodeId, part_id,&tile_info));}for (auto & future : futures)future.get();// 提交体数据输入HARC_TEST_SUCCESS(HAPI_CommitGeo(dst_session->get(), input_node_id));// 对节点进行 cookHARC_TEST_SUCCESS(HAPI_CookNode(dst_session->get(), input_node_id, nullptr));HARC_TEST_ASSERT(testharcVerifyInputVolume_HoudiniVolume(dst_session->get(), input_node_id, 0));
}

最后,用于管理session的函数(session创建函数,HAPI_IsSessionValid()和HAPI_CloseSession())共享一个互斥锁。但是它们不会干扰并发调用的常规HAPI函数(除了HAPI_CloseSession(),它会使session无效,如果随后将其传递给HAPI函数将导致未定义的行为)。

你始终可以安全地调用HAPI_IsSessionValid()来确定session是否有效。

这篇关于翻译HoudiniEngine官方文档:Sessions的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1143397

相关文章

C#实现将Office文档(Word/Excel/PDF/PPT)转为Markdown格式

《C#实现将Office文档(Word/Excel/PDF/PPT)转为Markdown格式》Markdown凭借简洁的语法、优良的可读性,以及对版本控制系统的高度兼容性,逐渐成为最受欢迎的文档格式... 目录为什么要将文档转换为 Markdown 格式使用工具将 Word 文档转换为 Markdown(.

详解如何使用Python构建从数据到文档的自动化工作流

《详解如何使用Python构建从数据到文档的自动化工作流》这篇文章将通过真实工作场景拆解,为大家展示如何用Python构建自动化工作流,让工具代替人力完成这些数字苦力活,感兴趣的小伙伴可以跟随小编一起... 目录一、Excel处理:从数据搬运工到智能分析师二、PDF处理:文档工厂的智能生产线三、邮件自动化:

Python实现自动化Word文档样式复制与内容生成

《Python实现自动化Word文档样式复制与内容生成》在办公自动化领域,高效处理Word文档的样式和内容复制是一个常见需求,本文将展示如何利用Python的python-docx库实现... 目录一、为什么需要自动化 Word 文档处理二、核心功能实现:样式与表格的深度复制1. 表格复制(含样式与内容)2

Maven项目中集成数据库文档生成工具的操作步骤

《Maven项目中集成数据库文档生成工具的操作步骤》在Maven项目中,可以通过集成数据库文档生成工具来自动生成数据库文档,本文为大家整理了使用screw-maven-plugin(推荐)的完... 目录1. 添加插件配置到 pom.XML2. 配置数据库信息3. 执行生成命令4. 高级配置选项5. 注意事

Python使用python-docx实现自动化处理Word文档

《Python使用python-docx实现自动化处理Word文档》这篇文章主要为大家展示了Python如何通过代码实现段落样式复制,HTML表格转Word表格以及动态生成可定制化模板的功能,感兴趣的... 目录一、引言二、核心功能模块解析1. 段落样式与图片复制2. html表格转Word表格3. 模板生

ubuntu系统使用官方操作命令升级Dify指南

《ubuntu系统使用官方操作命令升级Dify指南》Dify支持自动化执行、日志记录和结果管理,适用于数据处理、模型训练和部署等场景,今天我们就来看看ubuntu系统中使用官方操作命令升级Dify的方... Dify 是一个基于 docker 的工作流管理工具,旨在简化机器学习和数据科学领域的多步骤工作流。

浅谈Redis Key 命名规范文档

《浅谈RedisKey命名规范文档》本文介绍了Redis键名命名规范,包括命名格式、具体规范、数据类型扩展命名、时间敏感型键名、规范总结以及实际应用示例,感兴趣的可以了解一下... 目录1. 命名格式格式模板:示例:2. 具体规范2.1 小写命名2.2 使用冒号分隔层级2.3 标识符命名3. 数据类型扩展命

使用Python从PPT文档中提取图片和图片信息(如坐标、宽度和高度等)

《使用Python从PPT文档中提取图片和图片信息(如坐标、宽度和高度等)》PPT是一种高效的信息展示工具,广泛应用于教育、商务和设计等多个领域,PPT文档中常常包含丰富的图片内容,这些图片不仅提升了... 目录一、引言二、环境与工具三、python 提取PPT背景图片3.1 提取幻灯片背景图片3.2 提取

Android实现在线预览office文档的示例详解

《Android实现在线预览office文档的示例详解》在移动端展示在线Office文档(如Word、Excel、PPT)是一项常见需求,这篇文章为大家重点介绍了两种方案的实现方法,希望对大家有一定的... 目录一、项目概述二、相关技术知识三、实现思路3.1 方案一:WebView + Office Onl

Python实现word文档内容智能提取以及合成

《Python实现word文档内容智能提取以及合成》这篇文章主要为大家详细介绍了如何使用Python实现从10个左右的docx文档中抽取内容,再调整语言风格后生成新的文档,感兴趣的小伙伴可以了解一下... 目录核心思路技术路径实现步骤阶段一:准备工作阶段二:内容提取 (python 脚本)阶段三:语言风格调