我想在一个单独的线程中写输出,我知道这可以完成
>异步I / O.
>创建线程
> I / O完成端口
我有两类问题,即概念和特定代码.
概念性问题
什么是最好的方法.请注意,应用程序应该可以移植到Linux,但是,我不知道这对于我选择的1-3是多么重要,因为我会编写一个关于任何内核/ API特定的包装器.对我来说,最重要的标准是速度.我已经读过,选项1不太可能提高程序的性能,并且内核在任何情况下都会为i / o操作创建新的线程,所以为什么不立即使用选项(2),看起来好像很有用更容易编程(因为我没有使用选项(1)成功,请参阅下面的代码问题).
请注意,我阅读了https://stackoverflow.com/questions/3689759/how-can-i-run-a-specific-function-of-thread-asynchronously-in-c-c,但是根据应用程序的性质,我没有看到使用内容的动机.所以我希望有人能给我一些建议,在我的情况下最好.同样来自Johnson M. Hart的“Windows系统编程”一书,我知道建议使用线程,主要是因为它的简单性.但是,它也会最快吗?
代码问题
这个问题涉及到目前为止我为使异步I / O工作所做的尝试.我知道它是一个很大的代码,所以它不容易调查.无论如何,我真的很感激任何尝试.
为了减少执行时间,我尝试使用带有重叠结构的FILE_FLAGGED_OVERLAP的CreateFile()使用WINAPI通过新线程编写输出.我已经创建了一个示例程序,我试图让它工作.但是,我遇到了两个问题:
>当我删除已存在的文件时,文件仅以重叠模式打开(我尝试在不同模式下使用CreateFile(CREATE_ALWAYS,CREATE_NEW,OPEN_EXISTING),但这没有用).
>只有第一个WriteFile异步执行. WriteFile命令的其余部分是同步的.对于这个问题,我已经咨询了http://support.microsoft.com/kb/156932.似乎我遇到的问题与“对文件的任何写操作扩展其长度都是同步的”这一事实有关.我已经尝试通过增加文件大小/有效数据大小(代码中的注释区域)来解决这个问题.但是,我仍然没有让它发挥作用.我知道可能的情况是,为了最大限度地利用FILE_FLAG_NO_BUFFERING创建具有FILE_FLAG_NO_BUFFERING的异步io,但是我无法使其工作.
请注意,程序在执行路径中创建一个大约120mb的文件.另请注意,打印报表“不行”是不可取的,我希望看到“可以在后台工作”出现在我的屏幕上……这里出了什么问题?
#include <windows.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define ASYNC // remove this deFinition to run synchronously (i.e. using fwrite)
#ifdef ASYNC
struct _OVERLAPPED *pOverlapped;
HANDLE *pEventH;
HANDLE *pFile;
#else
FILE *pFile;
#endif
#define DIM_X 100
#define DIM_Y 150000
#define _PRINTERROR(msgs)\
{printf("file: %s,line: %d,%s",__FILE__,__LINE__,msgs);\
fflush(stdout);\
return 0;} \
#define _PRINTF(msgs)\
{printf(msgs);\
fflush(stdout);} \
#define _START_TIMER \
time_t time1,time2; \
clock_t clock1; \
time(&time1); \
printf("start time: %s",ctime(&time1)); \
fflush(stdout);
#define _END_TIMER\
time(&time2);\
clock1 = clock();\
printf("end time: %s",ctime(&time2));\
printf("elapsed processor time: %.2f\n",(((float)clock1)/CLOCKS_PER_SEC));\
fflush(stdout);
double aio_dat[DIM_Y] = {0};
double do_compute(double A,double B,int arr_len);
int main()
{
_START_TIMER;
const char *pName = "test1.bin";
DWORD dwBytesToWrite;
BOOL bErrorFlag = FALSE;
int j=0;
int i=0;
int fOverlapped=0;
#ifdef ASYNC
// create / open the file
pFile=CreateFile(pName,GENERIC_WRITE,// open for writing
0,// share write access
NULL,// default security
CREATE_ALWAYS,// create new/overwrite existing
FILE_FLAG_OVERLAPPED,// | FILE_FLAG_NO_BUFFERING,// overlapped file
NULL); // no attr. template
// check whether file opening was ok
if(pFile==INVALID_HANDLE_VALUE){
printf("%x\n",GetLastError());
_PRINTERROR("file not opened properly\n");
}
// make the overlapped structure
pOverlapped = calloc(1,sizeof(struct _OVERLAPPED));
pOverlapped->Offset = 0;
pOverlapped->OffsetHigh = 0;
// put event handle in overlapped structure
if(!(pOverlapped->hEvent = CreateEvent(NULL,TRUE,FALSE,NULL))){
printf("%x\n",GetLastError());
_PRINTERROR("error in createevent\n");
}
#else
pFile = fopen(pName,"wb");
#endif
// create some output
for(j=0;j<DIM_Y;j++){
aio_dat[j] = do_compute(i,j,DIM_X);
}
// determine how many bytes should be written
dwBytesToWrite = (DWORD)sizeof(aio_dat);
for(i=0;i<DIM_X;i++){ // do this DIM_X times
#ifdef ASYNC
//if(i>0){
//SetFilePointer(pFile,dwBytesToWrite,NULL,FILE_CURRENT);
//if(!(SetEndOfFile(pFile))){
// printf("%i\n",pFile);
// _PRINTERROR("error in set end of file\n");
//}
//SetFilePointer(pFile,-dwBytesToWrite,FILE_CURRENT);
//}
// write the bytes
if(!(bErrorFlag = WriteFile(pFile,aio_dat,pOverlapped))){
// check whether io pending or some other error
if(GetLastError()!=ERROR_IO_PENDING){
printf("lasterror: %x\n",GetLastError());
_PRINTERROR("error while writing file\n");
}
else{
fOverlapped=1;
}
}
else{
// if you get here output got immediately written; bad!
fOverlapped=0;
}
if(fOverlapped){
// do background,this msgs is what I want to see
for(j=0;j<DIM_Y;j++){
aio_dat[j] = do_compute(i,DIM_X);
}
for(j=0;j<DIM_Y;j++){
aio_dat[j] = do_compute(i,DIM_X);
}
_PRINTF("can do work in background\n");
}
else{
// not overlapped,this message is bad
_PRINTF("not ok\n");
}
// wait to continue
if((WaitForSingleObject(pOverlapped->hEvent,INFINITE))!=WAIT_OBJECT_0){
_PRINTERROR("waiting did not succeed\n");
}
// reset event structure
if(!(ResetEvent(pOverlapped->hEvent))){
printf("%x\n",GetLastError());
_PRINTERROR("error in resetevent\n");
}
pOverlapped->Offset+=dwBytesToWrite;
#else
fwrite(aio_dat,sizeof(double),DIM_Y,pFile);
for(j=0;j<DIM_Y;j++){
aio_dat[j] = do_compute(i,DIM_X);
}
for(j=0;j<DIM_Y;j++){
aio_dat[j] = do_compute(i,DIM_X);
}
#endif
}
#ifdef ASYNC
CloseHandle(pFile);
free(pOverlapped);
#else
fclose(pFile);
#endif
_END_TIMER;
return 1;
}
double do_compute(double A,int arr_len)
{
int i;
double res = 0;
double *xA = malloc(arr_len * sizeof(double));
double *xB = malloc(arr_len * sizeof(double));
if ( !xA || !xB )
abort();
for (i = 0; i < arr_len; i++) {
xA[i] = sin(A);
xB[i] = cos(B);
res = res + xA[i]*xA[i];
}
free(xA);
free(xB);
return res;
}
有用的链接
> http://software.intel.com/sites/products/documentation/studio/composer/en-us/2011/compiler_c/cref_cls/common/cppref_asynchioC_aio_read_write_eg.htm
> http://www.ibm.com/developerworks/linux/library/l-async/?ca=dgr-lnxw02aUsingPOISIXAIOAPI
> http://www.flounder.com/asynchexplorer.htm#Asynchronous%20I/O
我知道这是一个很大的问题,我想提前感谢所有人,他们在阅读它时遇到了麻烦,甚至可能会做出回应!
您处于正确的轨道:系统阻止您异步写入,因为每个WriteFile都会扩展文件的大小.但是,您正在进行错误的文件大小扩展.简单地调用SetFileSize实际上不会在MFT中保留空间.使用SetFileValidData函数.这将为您的文件分配集群(请注意它们将包含磁盘所具有的任何垃圾),您应该能够并行执行WriteFile和您的计算.
我会远离FILE_FLAG_NO_BUFFERING.我认为你的并行性表现更好吗?不要阻止缓存执行其工作.